如果结构可以实现 IDisposable,为什么它们不能有析构函数?

If structs can implement IDisposable, why can't they have destructors?

我阅读了类似question的已接受答案,部分答案是:

when structs are passed as parameters, they get passed by value: they are copied. Now you've got two structs with the same internal fields, and they're both going to attempt to clean up the same object. One will happen first, and so code that is using the other one afterwards will start to fail mysteriously... and then its own cleanup will fail

Dispose() 不是同样的问题吗?如果结构可以实现 IDisposable,不允许它们拥有终结器的原因是什么?

如果终结器的全部意义在于调用 Dispose(false) 以防程序员忘记调用 Dispose(),并且结构可以有 IDisposable.Dispose(),那么为什么不允许结构的终结器但是允许它们用于引用类型?

因为IDisposable只是一个接口。没有特殊处理。结构体可以实现接口,所以可以实现IDisposable.

然而,这并不意味着它没有意义。 IDisposable 的目的是释放非托管资源。一个结构可以有一个 reference 到一个非托管资源,这将从 Dispose 中受益(不用说,那个引用本身应该实现 IDisposable 并且有一个终结器)。

作为奖励,Dispose 通常用作 using 模式的一部分。您仅为 using 块创建实例,在 Dispose 之前保留一个引用,不涉及任何奇怪的事情。真的没有理由禁止它。

Doesn't this same problem apply to Dispose()?

有点,但不完全是。具体来说,"then its own cleanup will fail" 是可能的,但不太可能,因为 Dispose() 在同一对象上多次调用必须是安全的,并且在同一对象的不同副本上多次调用它通常不会有问题对象。

If structs can't have finalizers, why are they allowed to implement IDisposable?

允许它是自然行为;它为语言提供了更简单的规则。由于这不是程序员可能偶然出错的事情,因此在编译器中编写额外代码来拒绝这种情况的好处很小。


Jeroen Mostert 补充说,它甚至可以使结构实现很有意义 IDisposable:

IDisposable 可能只是因为它是某些其他代码的要求而被实现,即使 Dispose() 在这个特定类型上的实现绝对不会做任何事情。在这种情况下,不存在在不同副本上意外调用它的风险。这方面的一个例子是当结构实现 IEnumerator<T> 时,其中 IEnumerator<T> 反过来实现 IDisposable.