Demander à une méthode générique de lever un type d'exception spécifique en cas d'échec

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

  •  09-06-2019
  •  | 
  •  

Question

C'est vrai, je sais que je vais avoir l'air d'un idiot avec celui-là, mais mon cerveau est juste pas on passe à la vitesse supérieure ce matin.

Je veux avoir une méthode où je peux dire "si ça tourne mal, revenez avec ce type d'exception", n'est-ce pas ?

Par exemple, quelque chose comme (et ça ne marche pas):

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

Maintenant, ce qui me rend confus, c'est que nous SAVOIR que le type générique sera de type Exception en raison de la clause.Cependant, le code échoue car nous ne pouvons pas implicitement lancer Exception à ExType.Nous ne pouvons pas non plus le convertir explicitement, comme :

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

Comme cela échoue aussi..Donc est-ce que ce genre de chose est possible ? J'ai le fort sentiment que ça va être très simple, mais je passe une journée difficile avec cette vieille caboche, alors laisse-moi un peu de répit :P


Mise à jour

Merci pour vos réponses les gars, on dirait que ce n'était pas moi qui complet idiot!;)

D'accord alors Vgard et Sam m'a amené au point où je pouvais instancier le type correct, mais je suis évidemment resté bloqué parce que le message param est en lecture seule après l'instanciation.

Mat a mis le doigt sur la tête avec sa réponse, j'ai testé cela et tout fonctionne bien.Voici l'exemple de code :

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

Doux!:)

Merci les gars!

Était-ce utile?

La solution

Vous pouvez presque procéder comme ceci :

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

Cependant, cela ne compile pas car Exception.Message est en lecture seule.Il ne peut être attribué qu'en le transmettant au constructeur, et il n'existe aucun moyen de contraindre un type générique avec autre chose qu'un constructeur par défaut.

Je pense que vous devrez utiliser la réflexion (Activator.CreateInstance) pour "renouveller" le type d'exception personnalisé avec le paramètre message, comme ceci :

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

Modifier Oups, je viens de réaliser que tu voulais retour l'exception, ne la jetez pas.Le même principe s'applique, je vais donc laisser ma réponse telle quelle avec les instructions throw.

Autres conseils

Le seul problème avec la solution est qu'il est possible de créer une sous-classe d'Exception qui n'implémente pas de constructeur avec un seul paramètre de chaîne, donc l'exception MethodMissingException peut être levée.

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

J'ai instancié en ligne le type d'exception que je souhaite lancer, comme ceci :

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

Avez-vous plutôt essayé :

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

parce que j'ai le sentiment que mettre la contrainte générique n'est pas nécessaire comme toutes les exceptions jetables doit hériter de System.Exception de toute façon.

N'oubliez pas que les génériques acceptent les types hérités.

Je pense que, étant donné que toutes les exceptions devraient avoir un constructeur sans paramètre et avoir le Message propriété, donc ce qui suit devrait fonctionner :

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

Modifier:OK, Message est en lecture seule, vous devrez donc espérer que la classe implémente le constructeur Exception(string) à la place.

static ExType TestException<ExType>(string message) where ExType:Exception
{
    return new ExType(message);
}
Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top