Cyr*_*rus 3 .net c# exception try-catch 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);
}
}
Run Code Online (Sandbox Code Playgroud)
控制台输出为:
System.Exception: Exception 2
at Program.FixedUnalterableMethod() in ...\Program.cs:line 16
at Program.Main(String[] args) in ...\Program.cs:line 24
Run Code Online (Sandbox Code Playgroud)
问题是,如何得知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);
}
}
Run Code Online (Sandbox Code Playgroud)
该catch... when功能使您可以编写布尔表达式来检查异常。在这里,我检查消息(您给我的唯一区别事实),如果这是第一个例外,我会将其传递给store操作。
调用者使用此回调来存储第一个异常。
然后,它投票以捕获,然后才导致该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);
}
}
Run Code Online (Sandbox Code Playgroud)