Je sais que parfois innerException est nulle
Donc, ce qui suit pourrait échouer:
repEvent.InnerException = ex.InnerException.Message;
Existe-t-il un moyen ternaire rapide de vérifier si innerException est nulle ou non?
Est-ce ce que vous recherchez?
String innerMessage = (ex.InnerException != null)
? ex.InnerException.Message
: "";
Excellentes réponses jusqu'à présent. Sur une note similaire, mais différente, il existe parfois plusieurs niveaux d'exceptions imbriquées. Si vous voulez obtenir l'exception racine qui a été initialement lancée, quelle que soit sa profondeur, essayez ceci:
public static class ExceptionExtensions
{
public static Exception GetOriginalException(this Exception ex)
{
if (ex.InnerException == null) return ex;
return ex.InnerException.GetOriginalException();
}
}
Et en usage:
repEvent.InnerException = ex.GetOriginalException();
C'est drôle, je ne trouve rien de mal à Exception.GetBaseException () ?
repEvent.InnerException = ex.GetBaseException().Message;
La solution la plus simple consiste à utiliser une expression conditionnelle de base:
repEvent.InnerException = ex.InnerException == null ?
null : ex.InnerException.Message;
Pourquoi tant de récursions 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 un moyen beaucoup plus simple d’appliquer cela.
C'est une vieille question mais pour les futurs lecteurs:
En plus des réponses déjà postées, je pense que la bonne façon de procéder (lorsque vous pouvez avoir plusieurs InnerException) est Exception.GetBaseException, méthode
Si vous voulez l'instance d'exception, procédez comme suit:
repEvent.InnerException = ex.GetBaseException();
Si vous recherchez uniquement le message de cette façon:
repEvent.InnerException = ex.GetBaseException().Message;
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
.
Parfois aussi InnerException a une InnerException, vous pouvez donc utiliser une fonction récursive pour cela:
public string GetInnerException(Exception ex)
{
if (ex.InnerException != null)
{
return string.Format("{0} > {1} ", ex.InnerException.Message, GetInnerException(ex.InnerException));
}
return string.Empty;
}
Avec C # 6.0, vous pouvez le faire en une seule ligne.
repEvent.InnerException = ex.InnerException?.Message;
pour une autre fonctionnalité de C # 6.0, cliquez ici
Voici une autre implémentation possible qui ajoute les messages et les traces de pile afin que nous les obtenions complets:
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);
}
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;
}
}
}
Avec ce code, vous serez sûr de ne perdre aucun message d'exception interne
catch (Exception exception)
{
Logger.Error(exception.Message);
while (exception.InnerException != null)
{
exception = exception.InnerException;
Logger.Error(exception);
}
}
Oui:
if (ex.InnerException == null) {
// then it's null
}