在 C# 中,try-finally 如何捕获原始异常
in C# try-finally how to catch the original exception
我的简单例子是:
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
已经发生?
有没有办法在我的 StackTrace 中包含 Exception 1
(第 28 行)?
当然我不能修改FixedUnalterableMethod()
方法!
如果 "exception type" 完全相同,您可能别无选择,只能检查 Message
属性,这至少可以说是有问题的。
再次查看该代码,无论如何您只会看到 1 个异常,第 16 行的那个。
是的,这是可能的,虽然很讨厌!
一个鲜为人知的事实是,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);
}
}
感谢@Daniel Earwicker,工作解决方案是:
void FixedUnalterableMethod()
{
try
{
throw new Exception("Exception 1"); //line 12.
}
finally
{
throw new Exception("Exception 2"); //line 16.
}
}
void Method1()
{
bool CatchException(Exception ex)
{
//Log...
Console.WriteLine(ex.ToString());
return true;
}
try
{
FixedUnalterableMethod(); //line 24.
}
catch (Exception ex) when (CatchException(ex))
{
//do something with the lastest exception
}
}
我的简单例子是:
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
已经发生?
有没有办法在我的 StackTrace 中包含 Exception 1
(第 28 行)?
当然我不能修改FixedUnalterableMethod()
方法!
如果 "exception type" 完全相同,您可能别无选择,只能检查 Message
属性,这至少可以说是有问题的。
再次查看该代码,无论如何您只会看到 1 个异常,第 16 行的那个。
是的,这是可能的,虽然很讨厌!
一个鲜为人知的事实是,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);
}
}
感谢@Daniel Earwicker,工作解决方案是:
void FixedUnalterableMethod()
{
try
{
throw new Exception("Exception 1"); //line 12.
}
finally
{
throw new Exception("Exception 2"); //line 16.
}
}
void Method1()
{
bool CatchException(Exception ex)
{
//Log...
Console.WriteLine(ex.ToString());
return true;
}
try
{
FixedUnalterableMethod(); //line 24.
}
catch (Exception ex) when (CatchException(ex))
{
//do something with the lastest exception
}
}