为什么 C# 不允许在析构函数上使用访问修饰符?

发布于 2024-08-24 19:27:49 字数 538 浏览 6 评论 0原文

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

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

我尝试过公共、私有、受保护和内部。它在没有访问修饰符的情况下工作得很好。由于本文显示~析构函数本质上是受保护的语法糖Finalize 函数,让我觉得奇怪的是你不能在析构函数上使用至少 protected 。文章确实说“析构函数不能被调用。它们是自动调用的。”这就是这种行为的强制执行方式吗?

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

I was making a simple class for a small project and decided to just add a destructor for a quick impl instead of using IDisposable, and I came across a compiler error whenever there is a destructor with an access modifier on it.

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

I tried public, private, protected and internal. It worked fine with no access modifiers. Since this article shows that the ~destructor is essentially syntatic sugar for a protected Finalize function, it strikes me as odd that you cant use at least protected on the destructor. The article does say "Destructors cannot be called. They are invoked automatically." Is this how that behavior is enforced?

I ended up just implementing IDisposable anyway, but I am curious... is there some other reason why you cannot put access modifiers on a destructor?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(4

九公里浅绿 2024-08-31 19:27:49

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

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

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

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

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

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

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

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

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

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

The accessibility domain of a member declared in source code consists of the set of all sections of program text in which that member may be accessed.

An accessibility modifier modifies the contents of the accessibility domain.

An interesting fact about accessibility modifiers is that an accessibility modifier always makes the accessibility domain larger or keeps it the same size. An accessibility modifier never makes the accessibility domain smaller.

We desire that the accessibility domain of a destructor be always empty. That is, it should never be legal to access a destructor in any region of program text.

The reason for this is because we wish to provide to you the enforced invariant that a destructor for a particular instance is run exactly once in the lifetime of the object, at the end of said lifetime. ("Resurrection" of dead objects during finalization brings up interesting issues which I will discuss at a later date.) By disallowing access to the destructor we ensure that user code never calls a destructor early.

Therefore it would be foolish of us to allow the user to increase the size of the accessibility domain; we do not want to hand the user a tool to defeat this carefully-considered aspect of the design of the language.

Did you want to defeat this safety feature? Why? Can you describe a scenario in which it is important that you be able to call a destructor from some region of program text?

the destructor is essentially syntatic sugar for a protected Finalize function

Correct. The specification notes this in section 10.13. And note that the accessibility domain of the allegedly protected "Finalize" method is also empty; it may be neither overridden nor called.

We could have chosen some completely different mechanism to implement destructors, but that's the one we chose. The fact that we happened to choose some particular implementation strategy for the destructor feature has no particular bearing on the fact that the accessibility domain of a destructor should be enforced to remain empty for safety reasons.

幽梦紫曦~ 2024-08-31 19:27:49

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

public 意味着任何用户编写的代码都可以调用该方法等。

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

因此,在方法上放置访问修饰符是没有意义的。无法访问它,并且无法修改该访问权限。

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

An access modifier controls which scope of user-written-code can call the method.

public means any user-written-code can call the method, etc, etc.

However, destructors are not called by user-written-code. Destructors are called automatically by the GC. An access modifier means nothing to the GC.

Hence, putting an access-modifier on the method has no meaning. It cannot be accessed, and that access cannot be modified.

You might as well consider the access to a destructor to be "super-private", in that no one, not even the object itself, can actually call the destructor.

潇烟暮雨 2024-08-31 19:27:49

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

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

It's because, as you point out, "Destructors cannot be called. They are invoked automatically."

Having an access modifier on something that cannot be accessed is pointless.

暮倦 2024-08-31 19:27:49

您应该使用一次性模式。

C# 中的最终/处置模式

You should use the Disposable Pattern.

Finalize/Dispose pattern in C#

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文