【问题标题】:Why doesn't C# allow access modifiers on destructors?为什么 C# 不允许在析构函数上使用访问修饰符?
【发布时间】:2011-01-24 08:02:57
【问题描述】:

我正在为一个小项目创建一个简单的类,并决定只为快速 impl 添加一个析构函数,而不是使用 IDisposable,每当有一个带有访问修饰符的析构函数时,我都会遇到编译器错误。

public class MyClass
{
    public ~MyClass()
    {
        // clean resources
    }
}

我尝试了公共、私有、受保护和内部。它在没有访问修饰符的情况下运行良好。由于this article shows ~destructor 本质上是受保护的 Finalize 函数的语法糖,我觉得奇怪的是,您至少不能在析构函数上使用 protected。文章确实说“无法调用析构函数。它们会被自动调用。”这就是强制执行该行为的方式吗?

无论如何,我最终还是实现了IDisposable,但我很好奇...还有什么其他原因不能将访问修饰符放在析构函数上

【问题讨论】:

  • 如果析构函数是受保护方法的语法糖,你为什么希望能够放一个访问修饰符?

标签: c# destructor access-modifiers


【解决方案1】:

在源代码中声明的成员的可访问域由可以访问该成员的程序文本的所有部分组成。

可访问性修饰符修改可访问域的内容。

关于可访问性修饰符的一个有趣事实是,可访问性修饰符总是使可访问域更大 或保持相同大小。可访问性修饰符永远不会使可访问域变小

我们希望析构函数的可访问域始终为空。也就是说,从不任何中访问析构函数是合法的> 程序文本区域。

这样做的原因是因为我们希望向您提供强制不变量,即特定实例的析构函数在对象的生命周期中仅运行一次,在所述生命周期结束时。 (在完成过程中死对象的“复活”带来了一些有趣的问题,我将在稍后讨论。)通过禁止访问析构函数,我们确保用户代码永远不会提前调用析构函数。

因此,允许用户增加可访问域的大小是愚蠢的;我们不想给用户一个工具来打败语言设计的这个经过深思熟虑的方面。

想要禁用此安全功能吗?为什么?您能否描述一个场景,在该场景中,能够从程序文本的某个区域调用析构函数很重要?

析构函数本质上是受保护的 Finalize 函数的语法糖

正确。规范在第 10.13 节中对此进行了说明。请注意,据称受保护的“Finalize”方法的可访问域也是空的;它可能既不会被覆盖也不会被调用。

我们本可以选择一些完全不同的机制来实现析构函数,但这是我们选择的。我们碰巧为析构函数特性选择了一些特定的实现策略这一事实与出于安全原因应该强制析构函数的可访问域保持为空这一事实没有特别的关系。

【讨论】:

  • 在发帖之前,我实际上试图回答您的问题。由于您可以使用垃圾收集器主动处理对象,因此我想不出任何情况来显式调用没有简单替代方案的析构函数。除此之外,我不了解安全问题。谢谢你的另一个清晰的解释。
【解决方案2】:

访问修饰符控制用户编写代码的哪个范围可以调用该方法。

public 表示任何用户编写的代码都可以调用方法等。

但是,用户编写的代码不会调用析构函数。 GC 会自动调用析构函数。访问修饰符对 GC 没有任何意义。

因此,在方法上添加访问修饰符没有任何意义。无法访问,也无法修改该访问权限。

您不妨将对析构函数的访问视为“超级私有”,因为没有人,甚至对象本身都不能真正调用析构函数。

【讨论】:

  • 是的。静态构造函数也是如此。 “机密”关键字呢?
【解决方案3】:

这是因为,正如您所指出的,“无法调用析构函数。它们会被自动调用。”

对无法访问的东西使用访问修饰符是没有意义的。

【讨论】:

  • 就像把门把手放在墙上。
【解决方案4】:

您应该使用一次性模式。

Finalize/Dispose pattern in C#

【讨论】:

    猜你喜欢
    • 2018-09-29
    • 1970-01-01
    • 2014-04-01
    • 2016-05-02
    • 2011-04-12
    • 2016-12-11
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多