Pedindo um método genérico para lançar um tipo de exceção específico em FAIL

StackOverflow https://stackoverflow.com/questions/41397

  •  09-06-2019
  •  | 
  •  

Pergunta

Certo, eu sei que vou parecer um idiota com isso, mas meu cérebro está simplesmente não entrando em ação esta manhã.

Quero ter um método onde eu possa dizer “se der errado, volte com esse tipo de Exception”, certo?

Por exemplo, algo como (e isso não funciona):

    static ExType TestException<ExType>(string message) where ExType:Exception
    {
        Exception ex1 = new Exception();
        ExType ex = new Exception(message);
        return ex;
    }

Agora, o que está me confundindo é que nós SABER que o tipo genérico será do tipo Exception devido ao onde cláusula.No entanto, o código falha porque não podemos converter implicitamente Exceção para ExType.Também não podemos convertê-lo explicitamente, como:

    static ExType TestException<ExType>(string message) where ExType:Exception
    {
        Exception ex1 = new Exception();
        ExType ex = (ExType)(new Exception(message));
        return ex;
    }

Como isso também falha ..Então esse tipo de coisa é possível? Tenho uma forte sensação de que vai ser muito simples, mas estou tendo um dia difícil com o velho, então me dê uma folga: P


Atualizar

Obrigado pelas respostas pessoal, parece que não fui eu quem completo idiota!;)

OK então Vegard e Sam me levou ao ponto em que poderia instanciar o tipo correto, mas obviamente fiquei preso porque o mensagem param é somente leitura após a instanciação.

Matt acertou em cheio com sua resposta, eu testei isso e tudo funciona bem.Aqui está o código de exemplo:

    static ExType TestException<ExType>(string message) where ExType:Exception, new ()
    {
        ExType ex = (ExType)Activator.CreateInstance(typeof(ExType), message);
        return ex;
    }

Doce!:)

Obrigado rapazes!

Foi útil?

Solução

Você quase pode fazer assim:

static void TestException<E>(string message) where E : Exception, new()
{
    var e = new E();
    e.Message = message;
    throw e;
}

No entanto, isso não é compilado porque Exception.Message é somente leitura.Ele só pode ser atribuído passando-o para o construtor e não há como restringir um tipo genérico com algo diferente de um construtor padrão.

Acho que você teria que usar reflexão (Activator.CreateInstance) para "renovar" o tipo de exceção personalizado com o parâmetro mensagem, assim:

static void TestException<E>(string message) where E : Exception
{
    throw Activator.CreateInstance(typeof(E), message) as E;
}

Editar Ops, acabei de perceber que você está querendo retornar a exceção, não jogue-a.O mesmo princípio se aplica, então deixarei minha resposta como está com as instruções throw.

Outras dicas

O único problema com a solução é que é possível criar uma subclasse de Exception que não implemente um construtor com um único parâmetro de string, portanto, MethodMissingException pode ser lançada.

static void TestException<E>(string message) where E : Exception, new()
{
    try 
    {
      return Activator.CreateInstance(typeof(E), message) as E;
    } 
    catch(MissingMethodException ex) 
    {
      return new E();
    }
}

Tenho instanciado inline o tipo de exceção que desejo lançar, assim:

if (ItemNameIsValid(ItemName, out errorMessage))
    throw new KeyNotFoundException("Invalid name '" + ItemName + "': " + errorMessage);
if (null == MyArgument)
    throw new ArgumentNullException("MyArgument is null");

Você já tentou:

static T TestException<Exception>(string message)
{}

porque tenho a sensação de que não é necessário inserir a restrição genérica, pois todas as exceções que podem ser lançadas deve herdar de System.Exception de qualquer maneira.

Lembre-se de que os genéricos aceitam tipos herdados.

Acho que visto que todas as exceções deveriam ter um construtor sem parâmetros e ter o Message propriedade, então o seguinte deve funcionar:

static ExType TestException<ExType>(string message) where ExType:Exception
{
    ExType ex = new ExType();
    ex.Message = message;
    return ex;
}

Editar:OK, Message é somente leitura, então você terá que esperar que a classe implemente o construtor Exception(string).

static ExType TestException<ExType>(string message) where ExType:Exception
{
    return new ExType(message);
}
Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top