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

68

有时候innerException是空的。

所以以下代码可能会失败:

 repEvent.InnerException = ex.InnerException.Message; 

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


1
您可能需要重新考虑您接受的答案。jrista的答案比其他答案更好,因为InnerException可以有自己的InnerException。 - Ryan Lundy
4
请记住,ToString会遍历内部异常并将它们组合起来,这可以是记录日志时的便捷快捷方式。 - Steven Sudit
16个回答

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
您可以简单地写成这样:

您可以简单地写成这样:

repEvent.InnerException = ex.InnerException?.Message ?? string.Empty;

如果想获取其他类型的错误,可以像这样编写代码:

string exception = $"\n{nameof(AccountViewModel)}.{nameof(AccountCommand)}. \nMessage: {ex.Message}. \nInnerException:{ex.InnerException}. \nStackTrace: {ex.StackTrace}";

1

是的:

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

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

0

可以使用异常筛选器来获得更精确的定位。

catch (Exception ex) when (ex.InnerException != null) {...}

请在此处找到更多详细信息


0

我知道这已经很老了,也许已经在我没有看到的评论中得到了答案,但最近我需要它来实现重试策略,以捕获给定类型的任何内部异常。

public static class ExceptionExtensions
    {
        public static bool ThisOrInnerIs<T>(this Exception exception, out T casted) where T : Exception
        {
            casted = exception as T;
            if (exception is T) return true;
                        
            if (exception.InnerException != null)
            {
                return ThisOrInnerIs(exception.InnerException, out casted);
            }

            return false;
        }
    }

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接