在不使用while循环的情况下找到最内部的异常?
Posted
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了在不使用while循环的情况下找到最内部的异常?相关的知识,希望对你有一定的参考价值。
当C#抛出异常时,它可能有一个内部异常。我想要做的是获取最内部的异常,或者换句话说,没有内部异常的叶子异常。我可以在while循环中执行此操作:
while (e.InnerException != null)
e = e.InnerException;
但我想知道是否有一些我可以使用的单行代替。
Oneliner :)
while (e.InnerException != null) e = e.InnerException;
显然,你不能让它变得更简单。
正如Glenn McElhoe在this answer所说,这是唯一可靠的方式。
您可以使用递归在某个实用程序类中创建方法。
public Exception GetFirstException(Exception ex)
if(ex.InnerException == null) return ex; // end case
else return GetFirstException(ex.InnerException); // recurse
使用:
try
// some code here
catch (Exception ex)
Exception baseException = GetFirstException(ex);
建议的扩展方法(好主意@dtb)
public static Exception GetFirstException(this Exception ex)
if(ex.InnerException == null) return ex; // end case
else return GetFirstException(ex.InnerException); // recurse
使用:
try
// some code here
catch (Exception ex)
Exception baseException = ex.GetFirstException();
我相信Exception.GetBaseException()
与这些解决方案做同样的事情。
警告:从各种评论我们已经发现它并不总是字面上做同样的事情,并且在某些情况下,递归/迭代解决方案将进一步。它通常是最内部的异常,由于某些类型的异常覆盖了默认值,因此令人失望地不一致。但是,如果你捕获特定类型的异常并且合理地确定它们不是奇怪的(比如AggregateException)那么我会期望它获得合法的最内层/最早的异常。
通过InnerExceptions循环是唯一可靠的方法。
如果捕获的异常是AggregateException,则GetBaseException()
仅返回最内层的AggregateException。
http://msdn.microsoft.com/en-us/library/system.aggregateexception.getbaseexception.aspx
如果您不知道嵌套内部异常的深度,则无法绕过循环或递归。
当然,您可以定义一个抽象方法来抽象它:
public static class ExceptionExtensions
public static Exception GetInnermostException(this Exception e)
if (e == null)
throw new ArgumentNullException("e");
while (e.InnerException != null)
e = e.InnerException;
return e;
我知道这是一个老帖子,但我很惊讶没有人建议GetBaseException()
这是Exception
类的方法:
catch (Exception x)
var baseException = x.GetBaseException();
这是自.NET 1.1以来的问题。文档:http://msdn.microsoft.com/en-us/library/system.exception.getbaseexception(v=vs.71).aspx
有时您可能会有许多内部异常(许多冒泡异常)。在这种情况下,您可能想要这样做:
List<Exception> es = new List<Exception>();
while(e.InnerException != null)
es.add(e.InnerException);
e = e.InnerException
不是一行而是关闭:
Func<Exception, Exception> last = null;
last = e => e.InnerException == null ? e : last(e.InnerException);
事实上是如此简单,你可以使用Exception.GetBaseException()
Try
//Your code
Catch ex As Exception
MessageBox.Show(ex.GetBaseException().Message, My.Settings.MsgBoxTitle, MessageBoxButtons.OK, MessageBoxIcon.Error);
End Try
你必须循环,不得不循环,将循环移动到一个单独的函数更清洁。
我创建了一个扩展方法来处理这个问题。它返回指定类型的所有内部异常的列表,追溯Exception.InnerException和AggregateException.InnerExceptions。
在我的特定问题中,追逐内部异常比平常更复杂,因为异常是由通过反射调用的类的构造函数抛出的。我们捕获的异常有一个类型为TargetInvocationException的InnerException,我们实际需要查看的异常深埋在树中。
public static class ExceptionExtensions
public static IEnumerable<T> innerExceptions<T>(this Exception ex)
where T : Exception
var rVal = new List<T>();
Action<Exception> lambda = null;
lambda = (x) =>
var xt = x as T;
if (xt != null)
rVal.Add(xt);
if (x.InnerException != null)
lambda(x.InnerException);
var ax = x as AggregateException;
if (ax != null)
foreach (var aix in ax.InnerExceptions)
lambda(aix);
;
lambda(ex);
return rVal;
用法非常简单。例如,如果您想知道我们是否遇到过
catch (Exception ex)
var myExes = ex.innerExceptions<MyException>();
if (myExes.Any(x => x.Message.StartsWith("Encountered my specific error")))
// ...
以上是关于在不使用while循环的情况下找到最内部的异常?的主要内容,如果未能解决你的问题,请参考以下文章
我可以在不使用嵌入式 while_loop 的情况下使用 SDL 检查事件吗?