在C#中尝试最后如何捕获原始异常

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()方法!

Dan*_*ker 9

是的,尽管很讨厌,这是可能的!

鲜为人知的事实是,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)

  • 这是太棒了!一个可爱的小块,几乎总是无用但有趣的信息 (3认同)