C# - “析构函数不被继承”是什么意思?

时间:2009-12-08 22:52:47

标签: c# .net idisposable destructor finalization

C# Language Specification 3.0的第10.13节“析构函数”声明如下:

  

析构函数不是继承的。因此,除了可以在该类中声明的类之外,类没有析构函数。

C# Programming Guide的Destructors部分包含一个示例,演示如何调用继承层次结构中的析构函数,包括以下语句:

  

...自动调用...类的析构函数,按顺序从最派生到最少派生。

我用各种实际例子对此进行了调查,其中包括一个定义析构函数的基类,一个派生类,它继承自基类并且没有定义析构函数。创建派生类的实例,允许对实例的所有引用超出范围,然后强制执行垃圾收集,演示在派生类的实例完成时调用基类中定义的析构函数。

我的问题是“析构函数不被继承”实际意味着什么,因为虽然你不能显式调用析构函数,但是继承链中的析构函数会被自动调用,并且即使派生类也会调用基类析构函数class没有定义析构函数?

是否与垃圾收集器而不是C#语言/编译器实现最终化的一些微妙的语义区别有关?

编辑1:

虽然C#语言规范还声明“实例构造函数不是继承的”,但与构造函数相关的行为与析构函数有很大不同,并且更符合IMO与“未继承”的术语,如下例所示:

  public class ConstructorTestBase
  {
    public ConstructorTestBase(string exampleParam)
    {
    }
  }

  public class ConstructorTest: ConstructorTestBase
  {
    public ConstructorTest(int testParam)
      : base(string.Empty)
    {
    }
  }

  ...

  // The following is valid since there is a derived class constructor defined that
  // accepts an integer parmameter.
  ConstructorTest test1 = new ConstructorTest(5);

  // The following is not valid since the base class constructor is not inherited
  // by the derived class and the derived class does not define a constructor that
  // takes a string parameter.
  ConstructorTest test2 = new ConstructorTest("Test"); 

与析构函数相关的行为与此非常不同,如以下示例所示,该示例通过仅向基类添加析构函数来扩展先前的构造函数示例。

  public class ConstructorTestBase
  {
    public ConstructorTestBase(string exampleParam)
    {
    }

    ~ConstructorTestBase()
    {
      Console.WriteLine("~ConstructorTestBase()");
    }
  }

  ...

  ConstructorTest test1 = new ConstructorTest(5);
  test1 = null;
  GC.Collect();

上面的示例演示了在派生类的实例完成时将调用基类构造函数,即使派生类没有显式定义析构函数。

我的观点很简单,我遇到过很多人没有意识到或明白发生这种情况的原因,其中很大一部分原因是“析构函数不是继承的”声明。

编辑2:

C#语言规范还说明了以下内容,并给出了底层实现的代码示例:

  

通过覆盖System.Object上的虚拟方法Finalize来实现析构函数。   不允许C#程序覆盖此方法或调用它   (或覆盖它)直接。

由于幕后实现实际上是基于继承,如上所述,我认为我的问题是有效的,我认为到目前为止我收到的任何回复都没有解决这个问题正确 - “破坏者不被遗传”实际意味着什么?

1 个答案:

答案 0 :(得分:19)