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

时间:2009-09-21 20:08:36

标签: c# .net exception exception-handling

我知道有时innerException为null

所以以下内容可能会失败:

 repEvent.InnerException = ex.InnerException.Message; 

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

14 个答案:

答案 0 :(得分:77)

到目前为止很棒的答案。在类似但不同的注释中,有时存在多个嵌套异常级别。如果你想获得最初抛出的根异常,无论多深,你可以试试这个:

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

答案 1 :(得分:52)

这是你在找什么?

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

答案 2 :(得分:40)

这很有趣,我找不到Exception.GetBaseException()的任何问题?

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

答案 3 :(得分:16)

最简单的解决方案是使用基本条件表达式:

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

答案 4 :(得分:11)

为什么这些答案会有如此多的递归?

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

似乎是一种更直接的方式来实现这一点。

答案 5 :(得分:10)

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

除了已经发布的答案,我认为正确的方法(当你有多个InnerException时)是Exception.GetBaseException Method

如果你想要异常实例,你应该这样做:

repEvent.InnerException = ex.GetBaseException();

如果你只是这样寻找信息:

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

答案 6 :(得分:8)

使用C#6.0,您可以使用:

string message = 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

答案 7 :(得分:5)

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

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

答案 8 :(得分:5)

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

repEvent.InnerException = ex.InnerException?.Message; 

对于C#6.0的其他功能,请点击here

答案 9 :(得分:2)

使用此代码,您将确保没有丢失任何内部异常消息

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

答案 10 :(得分:1)

是:

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

答案 11 :(得分:1)

这是另一个可能的实现,它附加消息和堆栈跟踪,以便我们将它们填满:

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

答案 12 :(得分: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;
        }
    }
}

答案 13 :(得分:0)

可以使用异常过滤器来获得更精确的瞄准。

is_default

请找到更多详细信息here