2009-09-21 5 views
45

Je sais que parfois innerException est nulleMeilleur moyen de vérifier l'exception interne?

Alors ce qui suit peut échouer:

repEvent.InnerException = ex.InnerException.Message; 

est-il un moyen rapide ternaire pour vérifier si innerException est nulle ou non?

+1

Vous voudrez peut-être revoir votre réponse acceptée. La réponse de jrista est meilleure que les autres, car une InnerException peut avoir sa propre InnerException. –

+4

Gardez à l'esprit que ToString parcourt les exceptions internes et les combine pour vous. Cela peut être un raccourci pratique lors de la connexion. –

Répondre

49

Est-ce que vous cherchez?

String innerMessage = (ex.InnerException != null) 
         ? ex.InnerException.Message 
         : ""; 
+0

Aussi, est-ce juste moi, ou serait-il un peu plus propre si les arguments étaient retournés et le '! =' Changé en '=='. – Noldorin

+1

@Noldorin - Désolé mec, j'ai répondu à cela et n'a pas vérifié pour voir si j'étais le premier! @JL - Noldorin a été le premier à sortir de la goulotte avec la bonne réponse, veuillez lui transférer la réponse acceptée. –

+0

@Andrew: Heh, pas besoin de s'excuser. :) Je ne suis pas du genre à être contrarié par la question d'un sujet insignifiant, j'étais simplement curieux de savoir pourquoi JL était principalement. – Noldorin

1

Oui:

if (ex.InnerException == null) { 
    // then it's null 
} 
15

La solution la plus simple est d'utiliser une expression conditionnelle de base:

repEvent.InnerException = ex.InnerException == null ? 
    null : ex.InnerException.Message; 
+0

Aucun problème, juste que le code d'Andrew a renvoyé une chaîne. –

+0

@JL: En fait, mental renvoie une 'string' aussi. J'ai juste supposé à partir du code que vous appeliez la propriété 'string'' InnerException' (juste être confus?). Peu importe cependant. @Andrew: Merci. Et bien que je ne pense pas du tout, +1 au tien pour la courtoisie. – Noldorin

+0

@Nordorin, Ah je vois où le problème arrive, je suis allé chaîne parce que les exceptions ne sérialisent pas bien (si elles le font). –

71

Excellentes réponses jusqu'à présent. Sur une note similaire, mais différente, il existe parfois plus d'un niveau d'exceptions imbriquées. Si vous voulez obtenir l'exception de la racine qui a été initialement lancée, peu importe la profondeur, vous pouvez essayer ceci:

public static class ExceptionExtensions 
{ 
    public static Exception GetOriginalException(this Exception ex) 
    { 
     if (ex.InnerException == null) return ex; 

     return ex.InnerException.GetOriginalException(); 
    } 
} 

Et utilisé:

repEvent.InnerException = ex.GetOriginalException(); 
+0

Ai-je manqué quelque chose ici ou est ex.GetOriginalException() pour innerException pas de niveau supérieur ex? –

+0

Je ne suis pas sûr de ce que vous demandez. GetOriginalException renvoie l'exception d'origine qui a déclenché toute la chaîne d'exceptions, qu'il s'agisse d'une seule exception (aucune exception InnerException) ou de plusieurs niveaux d'InnerExceptions. – jrista

+0

Merci, cela m'a aidé à trouver l'InnerException d'une exception lancée par EntityFramework. –

5

Parfois aussi InnerException a une InnerException, vous peut utiliser une fonction récursive pour elle:

public string GetInnerException(Exception ex) 
{ 
    if (ex.InnerException != null) 
    { 
     return string.Format("{0} > {1} ", ex.InnerException.Message, GetInnerException(ex.InnerException)); 
    } 
    return string.Empty; 
} 
+1

Je suis tout pour avoir creusé l'exception la plus ancienne, mais il n'y a vraiment aucune raison de revenir ici. Boucle juste pendant que l'exception interne n'est pas nulle. –

+0

Est-ce que la récursivité est mauvaise ou quelque chose? – tster

+0

E.g. dans Entity Framework sont utilement des exceptions profondes. –

34

C'est drôle, je ne peux pas trouver quelque chose de mal avec Exception.GetBaseException()?

repEvent.InnerException = ex.GetBaseException().Message; 
+0

Génial !, vous n'avez pas besoin de faire une méthode personnalisée pour parcourir toutes les exceptions imbriquées. –

9

Son une vieille question, mais pour les futurs lecteurs:

En plus est Exception.GetBaseException Method

les réponses déjà affichées Je pense que la bonne façon de le faire (quand vous pouvez avoir plus d'un InnerException)

Si vous souhaitez que l'instance d'exception vous devriez faire ceci:

repEvent.InnerException = ex.GetBaseException(); 

Si vous cherchez seulement pour le message de cette façon:

repEvent.InnerException = ex.GetBaseException().Message; 
10

Pourquoi tant de récursion dans ces réponses?

public static class ExceptionExtensions 
{ 
    public static Exception GetOriginalException(this Exception ex) 
    { 
     while(ex.InnerException != null)ex = ex.InnerException; 
     return ex; 
    } 
} 

Cela semble être une façon beaucoup plus simple de mettre en œuvre ceci.

1

Voici une autre mise en œuvre possible que les messages et ajoute traces de pile de sorte que nous obtenons pleins:

private static Tuple<string, string> GetFullExceptionMessageAndStackTrace(Exception exception) 
{ 
    if (exception.InnerException == null) 
    { 
     if (exception.GetType() != typeof(ArgumentException)) 
     { 
      return new Tuple<string, string>(exception.Message, exception.StackTrace); 
     } 
     string argumentName = ((ArgumentException)exception).ParamName; 
     return new Tuple<string, string>(String.Format("{0} With null argument named '{1}'.", exception.Message, argumentName), exception.StackTrace); 
    } 
    Tuple<string, string> innerExceptionInfo = GetFullExceptionMessageAndStackTrace(exception.InnerException); 
    return new Tuple<string, string>(
    String.Format("{0}{1}{2}", innerExceptionInfo.Item1, Environment.NewLine, exception.Message), 
    String.Format("{0}{1}{2}", innerExceptionInfo.Item2, Environment.NewLine, exception.StackTrace)); 
} 


[Fact] 
public void RecursiveExtractingOfExceptionInformationOk() 
{ 
    // Arrange 
    Exception executionException = null; 
    var iExLevelTwo = new NullReferenceException("The test parameter is null"); 
    var iExLevelOne = new ArgumentException("Some test meesage", "myStringParamName", iExLevelTwo); 
    var ex = new Exception("Some higher level message",iExLevelOne); 

    // Act 
    var exMsgAndStackTrace = new Tuple<string, string>("none","none"); 
    try 
    { 
     exMsgAndStackTrace = GetFullExceptionMessageAndStackTrace(ex); 
    } 
    catch (Exception exception) 
    { 
     executionException = exception; 
    } 

    // Assert 
    Assert.Null(executionException); 

    Assert.True(exMsgAndStackTrace.Item1.Contains("The test parameter is null")); 
    Assert.True(exMsgAndStackTrace.Item1.Contains("Some test meesage")); 
    Assert.True(exMsgAndStackTrace.Item1.Contains("Some higher level message")); 
    Assert.True(exMsgAndStackTrace.Item1.Contains("myStringParamName")); 

    Assert.True(!string.IsNullOrEmpty(exMsgAndStackTrace.Item2)); 

    Console.WriteLine(exMsgAndStackTrace.Item1); 
    Console.WriteLine(exMsgAndStackTrace.Item2); 
} 
7

Avec C# 6.0, vous pouvez utiliser:

string message = exception.InnerException?.Message ?? "";

Cette ligne de code est similaire à:

string message = exception.InnerException == null ? "" : exception.InnerException.Message.

https://msdn.microsoft.com/en-us/library/ty67wk28.aspx

http://blogs.msdn.com/b/jerrynixon/archive/2014/02/26/at-last-c-is-getting-sometimes-called-the-safe-navigation-operator.aspx

+0

+1 opérateurs null-conditionnels et null-coalescents. L'utilisation de '(ex.InnerException? .Message ??" ")' est pratique, lisible et sécurisée. – dakab

1
class MyException : Exception 
{ 
    private const string AMP = "\r\nInnerException: "; 
    public override string Message 
    { 
     get 
     { 
      return this.InnerException != null ? base.Message + AMP + this.InnerException.Message : base.Message; 
     } 
    } 

    public override string StackTrace 
    { 
     get 
     { 
      return this.InnerException != null ? base.StackTrace + AMP + this.InnerException.StackTrace : base.StackTrace; 
     } 
    } 
} 
1

Avec ce code, vous serez sûr que vous did't perdre des messages d'exception interne

catch (Exception exception) 
{ 
    Logger.Error(exception.Message); 
    while (exception.InnerException != null) 
    { 
     exception = exception.InnerException; 
     Logger.Error(exception); 
    } 
} 
2

avec C# 6.0, vous pouvez le faire dans un ligne.

repEvent.InnerException = ex.InnerException?.Message; 

pour d'autres caractéristique de C# 6.0 cliquez here

+0

La meilleure partie avec le code ci-dessus est, vous n'avez pas besoin de vous soucier de l'exception null pointeur i.e vérifiant null avant de l'utiliser (explicitement). –

Questions connexes