检查内部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
。
有时候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,请点击这里