检查内部exception的最佳方法是什么?

我知道有时innerException是null

所以以下可能会失败:

repEvent.InnerException = ex.InnerException.Message; 

有没有一个快速三元的方法来检查是否innerException是否为空?

这是你想要的?

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

迄今为止的好答案。 在一个类似的,但不同的说明,有时有不止一个层次的嵌套exception。 如果你想得到最初抛出的根exception,不pipe多深,你可以试试这个:

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

并在使用中:

 repEvent.InnerException = ex.GetOriginalException(); 

这很有趣,我找不到Exception.GetBaseException()有什么问题吗?

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

最简单的解决scheme是使用基本的条件expression式:

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

为什么在这些答案这么多的recursion?

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

看起来像一个更直接的方式来实现这一点。

这是一个老问题,但对未来的读者来说:

除了已经发布的答案,我认为正确的方法来做到这一点(当你可以有多个InnerException)是Exception.GetBaseException方法

如果你想要这个exception,你应该这样做:

 repEvent.InnerException = ex.GetBaseException(); 

如果您只是以这种方式寻找信息:

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

用C#6.0你可以使用:

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

这行代码类似于:

string message = exception.InnerException == null ? "" : exception.InnerException.Message 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

有时候InnerException也有一个InnerException,所以你可以使用recursion函数:

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

是:

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

这里是另一个可能的实现,它追加消息和堆栈跟踪,所以我们得到它们满:

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

有了这个代码,你可以确定你没有丢失任何内部的exception信息

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

使用C#6.0,你可以在一行中完成。

 repEvent.InnerException = ex.InnerException?.Message; 

对于C#6.0的其他function,请点击这里