c# - 在 C# try-finally 中如何捕获原始异常
问题描述
我的简单例子是:
void FixedUnalterableMethod()
{
try
{
throw new Exception("Exception 1"); //line 12.
}
finally
{
throw new Exception("Exception 2"); //line 16.
}
}
void Method1()
{
try
{
FixedUnalterableMethod(); //line 24.
}
catch (Exception ex)
{
var messageWithStackTrace = ex.ToString(); //line 28.
Console.WriteLine(messageWithStackTrace);
}
}
控制台输出为:
System.Exception: Exception 2
at Program.FixedUnalterableMethod() in ...\Program.cs:line 16
at Program.Main(String[] args) in ...\Program.cs:line 24
问题是,如何得知Exception 1
已经发生?有没有办法包含Exception 1
在我的 StackTrace 中(第 28 行)?
当然我不能修改FixedUnalterableMethod()
方法!
解决方案
是的,这是可能的,虽然很讨厌!
一个鲜为人知的事实是 CLR 异常finally
在实际捕获到异常之前不会导致块的执行。这在某种程度上是伪装的,因为如果没有捕获异常(并使其脱离Main
),则 CLR 托管代码的默认行为是finally
为您运行块,从而产生它们始终运行的错觉。
但是,有一种方法可以在捕获异常之前对其进行检查,以决定是否要捕获它。试试这个:
static bool StoreFirstException(Exception x, Action<Exception> store)
{
if (x.Message == "Exception 1")
{
store(x);
}
return true;
}
static void Method1()
{
Exception firstException = null;
try
{
FixedUnalterableMethod(); //line 24.
}
catch (Exception ex) when (StoreFirstException(ex, x => firstException = x))
{
Console.WriteLine(firstException);
Console.WriteLine(ex);
}
}
该catch... when
功能允许您编写一个布尔表达式来检查异常。在这里,我检查消息(您给我的唯一区别事实),如果它是第一个异常,我将其传递给store
操作。
调用者使用此回调来存储第一个异常。
然后它投票给 catch,这只会导致finally
块执行,这会引发第二个异常。相同的when
子句对其进行了检查,但这次没有将其提供给store
. 所以我在catch
块中有两个例外,我把它们都记录下来。我的控制台使用正确的源代码行号显示了两个异常。
这是不查看消息的版本;它只是假设它看到的第一个异常一定是有趣的。使用嵌套函数也更整洁:
static void Method1()
{
Exception firstException = null;
bool StoreFirstException(Exception x)
{
if (firstException == null) firstException = x;
return true;
}
try
{
FixedUnalterableMethod(); //line 24.
}
catch (Exception ex) when (StoreFirstException(ex))
{
Console.WriteLine(firstException);
Console.WriteLine(ex);
}
}
推荐阅读
- android - 意图进行另一个活动后如何在recyclerview中保存复选框的值
- javascript - RangeError:调度操作时超出了最大调用堆栈大小
- java - Google API 为 CDN 缓存失效抛出 Rate Limit Exceeded 403 异常
- javascript - 表格中某些列的水平滚动?
- amazon-web-services - 来自坏节点的 EMR 容器上的 SPARK
- javascript - 如何在 JavaScript 文件中配置类型以获取自动建议?
- ios - 如果我的模型对象的属性是自定义对象的数组,我如何让用户将对象附加到它?
- java - 来自命令行的 Spring Boot 参数
- bash - 优化查找 BASH 数组中最大元素的索引
- vb.net - 如何限制运行的应用程序数量?