Solicitar un método genérico para generar un tipo de excepción específico en caso de FALLO

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

  •  09-06-2019
  •  | 
  •  

Pregunta

Bien, sé que voy a parecer un completo idiota con esto, pero mi cerebro simplemente no poniendo en marcha esta mañana.

Quiero tener un método donde pueda decir "si sale mal, vuelve con este tipo de excepción", ¿verdad?

Por ejemplo, algo como (y esto no funciona):

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

Ahora lo que me confunde es que nosotros SABER que el tipo genérico va a ser de tipo Excepción debido a la dónde cláusula.Sin embargo, el código falla porque no podemos transmitir implícitamente Excepción a Tipo Ex.Tampoco podemos convertirlo explícitamente, como por ejemplo:

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

Como eso también falla ...Entonces ¿Es posible este tipo de cosas? Tengo el fuerte presentimiento de que va a ser muy simple, pero estoy teniendo un día difícil con el viejo, así que déjame un poco de holgura :P


Actualizar

Gracias por las respuestas chicos, parece que no fui yo quien completo ¡estúpido!;)

OK entonces Vegard y Sam me llevó al punto donde podía crear una instancia del tipo correcto, pero luego obviamente me quedé atascado porque el mensaje param es de solo lectura después de la creación de instancias.

Mate Dio en el clavo con su respuesta, lo he probado y todo funciona bien.Aquí está el código de ejemplo:

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

¡Dulce!:)

¡Gracias chicos!

¿Fue útil?

Solución

Casi puedes hacerlo así:

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

Sin embargo, eso no se compila porque Exception.Message es de solo lectura.Sólo se puede asignar pasándolo al constructor y no hay forma de restringir un tipo genérico con algo que no sea un constructor predeterminado.

Creo que tendrías que usar la reflexión (Activator.CreateInstance) para "renovar" el tipo de excepción personalizado con el parámetro de mensaje, así:

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

Editar Ups, me acabo de dar cuenta de que quieres hacerlo. devolver la excepción, no tirarla.Se aplica el mismo principio, así que dejaré mi respuesta tal como está con las declaraciones de lanzamiento.

Otros consejos

El único problema con la solución es que es posible crear una subclase de Exception que no implementa un constructor con un único parámetro de cadena, por lo que se podría generar MethodMissingException.

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();
    }
}

He estado creando instancias en línea del tipo de excepción que quiero lanzar, así:

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

¿Has probado, en su lugar:

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

porque tengo la sensación de que poner la restricción genérica no es necesario como todas las excepciones que se pueden lanzar debe heredar de System.Exception de todos modos.

Recuerde que los genéricos aceptan tipos heredados.

Creo que, dado que todas las excepciones deberían tener un constructor sin parámetros y tener la Message propiedad, por lo que lo siguiente debería funcionar:

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

Editar:Bien, el mensaje es de solo lectura, por lo que tendrás que esperar que la clase implemente el constructor Exception(string) en su lugar.

static ExType TestException<ExType>(string message) where ExType:Exception
{
    return new ExType(message);
}
Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top