如果您所做的只是抛出捕获的异常,是否需要 catch 块?

Do you need a catch block if all you're doing is throwing the caught exception?

我发现了一些他们想要传播异常的代码,但他们想要事先 运行 一些清理代码,所以自然地使用 Try/Catch/Finally。但是......他们实际上并没有做任何例外,只是转发它。我的理解是在那些情况下不需要 catch 块,但有人说它实际上是。我不确定那些这样做的人是否正确。

具体来说,Microsoft 的 documentation on Try-Catch 表示如下...

Within a handled exception, the associated finally block is guaranteed to be run. However, if the exception is unhandled, execution of the finally block is dependent on how the exception unwind operation is triggered. That, in turn, is dependent on how your computer is set up.

电脑跟它有什么关系?除了使用 FailFast 的例外(没有双关语意),调用它的进一步的 try-catch 块不会正确捕获此异常吗?如果那是他们的意思,man 那是一种尴尬的表达方式!

不过,我认为这证明不需要 catch{ throw; },对吗?

考虑以下代码...

public static BitmapImage MakeBitmapImage(byte[] bytes){

    var ms = new MemoryStream(bytes);

    try{
        var bitmapImage = new BitmapImage();

        bitmapImage.BeginInit();
            bitmapImage.CacheOption = BitmapCacheOption.OnLoad;
            bitmapImage.StreamSource = ms;
        bitmapImage.EndInit();

        return bitmapImage;
    }
    catch{
        throw;
    }
    finally{
        ms.Close();
        ms.Dispose();
    }
}

如果无法加载位图,难道不能像这样重写(没有 catch 块)来传播吗?

public static BitmapImage MakeBitmapImage(byte[] bytes){

    var ms = new MemoryStream(bytes);

    try{
        var bitmapImage = new BitmapImage();

        bitmapImage.BeginInit();
            bitmapImage.CacheOption = BitmapCacheOption.OnLoad;
            bitmapImage.StreamSource = ms;
        bitmapImage.EndInit();

        return bitmapImage;
    }
    finally{
        ms.Close();
        ms.Dispose();
    }
}

我不完全确定作者的意思,但我有根据的猜测是“您的计算机是如何设置的”。真正的意思是“你的架构如何处理展开”。这在 ARM 和 x86 中可能不同。

https://github.com/dotnet/runtime/blob/master/docs/design/coreclr/botr/clr-abi.md#general-unwindframe-layout

不需要 catch 块,也不需要 try 块:如果他们试图保证清理,他们可以只使用 using 语句,因为即使有异常,它也能工作。

我正要说这是一个无用的空洞。但是在更详细地阅读了您的链接文档之后,情况并非如此。

在某些情况下,运行时可能会在不展开线程堆栈和 运行 任何 finally 块的情况下终止您的进程。也许当(且仅当)根本没有 catch 处理程序时。您的程序无论如何都会崩溃,或者可能由于在另一个线程中处理而崩溃,您可能不关心这种区别。

在 dotnet 核心中,对于某些类型的故障,运行时可能会调用 Environment.FailFast 并立即崩溃。尽管我认为这仅适用于没有任何调用堆栈的故障,例如恢复执行上下文时发生的异常。同样,其他线程可能不会展开。

但是对于任何处理托管资源的 finally 块来说,这绝对没有意义。我只担心执行其他外部操作(如文件重命名)的 finally 块。然后你将需要测试实际行为是什么。