C# 检查内部异常的最佳方法?
我知道有时候innerException是空的 因此,以下操作可能会失败:C# 检查内部异常的最佳方法?,c#,.net,exception,exception-handling,C#,.net,Exception,Exception Handling,我知道有时候innerException是空的 因此,以下操作可能会失败: repEvent.InnerException = ex.InnerException.Message; 是否有一种快速检查innerException是否为null的方法?是: if (ex.InnerException == null) { // then it's null } 最简单的解决方案是使用基本条件表达式: repEvent.InnerException = ex.InnerExcepti
repEvent.InnerException = ex.InnerException.Message;
是否有一种快速检查innerException是否为null的方法?是:
if (ex.InnerException == null) {
// then it's null
}
最简单的解决方案是使用基本条件表达式:
repEvent.InnerException = ex.InnerException == null ?
null : ex.InnerException.Message;
这就是你要找的吗
String innerMessage = (ex.InnerException != null)
? ex.InnerException.Message
: "";
到目前为止,答案很好。类似但不同的是,有时存在多个级别的嵌套异常。如果要获取最初抛出的根异常,无论其深度有多深,都可以尝试以下方法:
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();
有时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;
}
真有趣,我找不出有什么问题吗
这是一个老问题,但对未来的读者来说: 除了已经发布的答案之外,我认为正确的方法是(当您可以有多个InnerException时) 如果需要异常实例,应执行以下操作:
repEvent.InnerException = ex.GetBaseException();
如果您仅以这种方式查找邮件:
repEvent.InnerException = ex.GetBaseException().Message;
为什么这些答案中有这么多递归
public static class ExceptionExtensions
{
public static Exception GetOriginalException(this Exception ex)
{
while(ex.InnerException != null)ex = ex.InnerException;
return ex;
}
}
这似乎是一种更直接的实现方式。下面是另一种可能的实现,它附加消息和堆栈跟踪,以便我们将它们填满:
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);
}
私有静态元组GetFullExceptionMessageAndStackTrace(异常)
{
if(exception.InnerException==null)
{
if(exception.GetType()!=typeof(ArgumentException))
{
返回新元组(exception.Message、exception.StackTrace);
}
字符串argumentName=((ArgumentException)exception).ParamName;
返回新元组(String.Format(“{0}带有名为“{1}.”的空参数),exception.Message,argumentName),exception.StackTrace);
}
Tuple innerExceptionInfo=GetFullExceptionMessageAndStackTrace(exception.InnerException);
返回新元组(
String.Format(“{0}{1}{2}”、innerExceptionInfo.Item1、Environment.NewLine、exception.Message),
格式(“{0}{1}{2}”,innerExceptionInfo.Item2,Environment.NewLine,exception.StackTrace));
}
[事实]
public void recursiveExtractionofExceptionFormationOK()递归提取
{
//安排
异常executionException=null;
var iExLevelTwo=新的NullReferenceException(“测试参数为null”);
var iExLevelOne=新的ArgumentException(“某些测试会议”,“myStringParamName”,iExLevelTwo);
var ex=新异常(“某个更高级别的消息”,iExLevelOne);
//表演
var exMsgAndStackTrace=新元组(“无”、“无”);
尝试
{
exMsgAndStackTrace=GetFullExceptionMessageAndStackTrace(ex);
}
捕获(异常)
{
executionException=异常;
}
//断言
Assert.Null(executionException);
True(exMsgAndStackTrace.Item1.Contains(“测试参数为null”);
True(exMsgAndStackTrace.Item1.Contains(“一些测试会议”);
True(exMsgAndStackTrace.Item1.Contains(“某个更高级别的消息”);
True(exMsgAndStackTrace.Item1.Contains(“myStringParamName”));
Assert.True(!string.IsNullOrEmpty(exMsgAndStackTrace.Item2));
Console.WriteLine(exMsgAndStackTrace.Item1);
控制台写入线(exMsgAndStackTrace.Item2);
}
使用C#6.0,您可以使用:
string message=exception.InnerException?.message??“
这行代码类似于:
string message=exception.InnerException==null?“”:exception.InnerException.Message
使用此代码,您可以确保没有丢失任何内部异常消息
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的其他功能,单击,可以使用异常过滤器来获得更精确的瞄准
catch(Exception ex)when(ex.InnerException!=null){…}
请查找更多详细信息另外,是我自己的问题,还是如果参数被翻转并且
,看起来会更干净一点=代码>改为==
@Noldorin-对不起,伙计,我回答了这个问题,没有检查我是否是第一个@JL-Noldorin是第一个回答正确的人,请把接受的答案转给他。@Andrew:Heh,不需要道歉。:)我不是一个为一件小事感到不安的人,我只是好奇JL的主要原因。有效,但不适用于多个嵌套的例外情况。您可能希望重新访问您已接受的答案。jrista的答案比其他的好,因为InnerException可以有自己的InnerException。请记住,ToString遍历内部异常并为您组合它们。这是记录日志时一条方便的捷径。完全没有问题,只是Andrew的代码返回了一个字符串。@JL:实际上,mind也返回了一个字符串。我只是从代码中假设您正在调用字符串
属性InnerException
(可能会混淆吗?)。不过没关系@安德鲁:谢谢。尽管我一点也不介意,@Nordorin,啊,我知道问题出在哪里了,我使用字符串是因为异常序列化不好(如果它们确实序列化的话)。@JL:NET framework附带的异常序列化很好,因为它们都有反序列化构造函数。自定义异常可能无法正确序列化,但添加反序列化构造函数并重写GetObjectData非常容易。第三方扩展可以通过序列化代理进行序列化。我完全支持深入挖掘最古老的异常,但这里确实没有理由递归。只要在内部异常不为null的情况下循环就行了。递归是邪恶的还是什么?例如,在实体框架中,深层次的异常是有用的。递归不是邪恶的,但它可能很昂贵,所以如果您不需要它,就不要使用它。在内部异常的情况下,您不需要一直将当前状态推到堆栈上,这样就可以继续您停止的操作,那么为什么要使用递归并为此付出代价呢?还有ca
catch (Exception exception)
{
Logger.Error(exception.Message);
while (exception.InnerException != null)
{
exception = exception.InnerException;
Logger.Error(exception);
}
}
repEvent.InnerException = ex.InnerException?.Message;