在C#中,函数名前的波浪线表示什么?

187

我正在查看一些代码,其中有这个语句:

~ConnectionManager()
{
    Dispose(false);
}

该类实现了IDisposable接口,但我不知道波浪线(~)与此有何关系。

6个回答

237

~是析构函数

  1. 析构函数会自动调用,不能显式地调用。
  2. 析构函数不能重载。因此,一个类最多只能有一个析构函数。
  3. 析构函数不会被继承。因此,一个类除了自己声明的析构函数外,没有其他析构函数。
  4. 析构函数不能用于结构体。它们仅用于类。 当任何代码都无法使用实例时,该实例将变得可销毁。
  5. 实例被销毁后,其继承链中的析构函数将按照从最派生到最基本的顺序依次调用。
  6. 在实例变得可销毁之后,析构函数的执行可能随时发生。

Finalize

在C#中,Finalize方法执行标准C++析构函数的操作。在C#中,您不需要使用名称Finalize - 您可以使用C++析构函数语法,在类名前放置波浪号(~)符号。

Dispose

最好在Close()或Dispose()方法中处置对象,以便类的用户可以显式地调用它们。GC会调用Finalize(析构函数)。

IDisposable接口告诉世界,您的类持有需要释放的资源,并为用户提供释放它们的方法。如果确实需要在类中实现终结器,您的Dispose方法应使用GC.SuppressFinalize()方法来确保抑制实例的终结。

使用哪种方式?

不能显式调用析构函数。垃圾回收器将调用您的析构函数。如果您要处理珍贵的不受管理的资源(例如文件句柄),并希望尽快关闭和处置它们,您应该实现IDisposable接口。


3
我不知道过去是怎么样的,但现在析构函数是可以被继承的。请查看此链接以获取更多信息(查看末尾示例):http://msdn.microsoft.com/en-us/library/66x5fx1b.aspx - RononDex
1
@RononDex,你链接的页面上第3点明确指出“不能继承终结器”,这与你的评论相矛盾。不过,这一切都有点令人困惑,因为虽然它们不能被继承,但是“从最派生到最不派生的所有实例的Finalize方法会递归调用”。请注意,这与可继承析构函数的行为不同。 - Mark Amery
@MarkAmery 哦,我明白了,所以基本上它们的调用顺序与继承的内容相反? - RononDex
那么,如果反编译生成的某些C#代码有这样一个方法,它可以安全地被删除吗?这似乎得到了证实,因为它没有任何引用。 - Jacob Stamm

46

这是一个终结器。说实话,你很少需要编写终结器。只有在以下情况下才需要编写终结器:

  • 您直接访问非托管资源(例如通过IntPtr),并且您无法使用使其更容易的SafeHandle
  • 您正在实现未密封的类中的IDisposable。(我的偏好是密封类,除非它们专门设计用于继承。)在这种情况下,终结器是规范Dispose模式的一部分。

9

它用于指示类的析构函数。


12
根据阅读的 C# 规范不同,两种说法都是正确的。最近的微软规范(统一的 C# 3.0)称其为析构函数(比如第 10.13 节),但 ECMA 规范则称其为终结器。 - Jon Skeet
@1800INFORMATION:语法元素的正确称呼是析构函数。如果一个类有析构函数,C#编译器将自动生成一个终结器,其中包括一个通常无用的try/finally块,以确保调用父级Finalize方法。大多数关于析构函数的事情也适用于终结器,反之亦然,但这些术语的含义略有不同。 - supercat

5
与 C++ 相同,它是析构函数;但在 C# 中,您不需要显式调用它,当对象被垃圾回收器回收时,它会自动调用。

3

请查看析构函数(C#编程指南)。但要注意,与C++不同的是,程序员无法控制何时调用析构函数,因为这由垃圾收集器决定。


0

4
正确的术语应为“析构函数/终结器”,而不是“解构函数”。解构函数指的是用于解构构造函数的语法。 - Eriawan Kusumawardhono

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接