抽象类的析构函数

本文关键字:析构函数 抽象类 | 更新日期: 2023-09-27 18:02:49

在c++中,我知道当打算从基类继承时通常应该使用虚析构函数。然而,对于c#,我不确定应该做什么。考虑下面的代码:

public abstract class Character
{
    private string characterName;
    public int health;
    Character()
    {
    }
    ~Character(){
    }
    public virtual void SetCharacterName( string tempName )
    {
        characterName = tempName;
    }
    public virtual string GetCharacterName( )
    {
        return characterName;
    }
}
(注:我听说Unity3Ds的c#实现与标准略有不同。也许忽略一些小的格式错误,代码似乎是功能性的…)

我的第一反应是将~Character()析构函数定义为虚的,方法是:

virtual ~Character(){
}

但是这样做会导致IDE返回错误。

在c#中,对希望继承的抽象类使用虚析构函数是必要的还是标准的?或者是否有其他方法可以在c#中创建虚析构函数?

抽象类的析构函数

c#没有确定性销毁。实际上,它本身并没有析构函数:它有终结器和IDisposable

当GC需要对对象实例进行垃圾收集时,它将清理这些东西。当应用程序域终止时,所有对象最终都会以这样或那样的方式被清理,但给定的对象可能会在应用程序域的持续时间内徘徊。在您的情况下,您不需要做任何事情,因为您的对象没有需要清理的资源。当GC清除未引用的对象时,它们将被正确地处理。

大多数情况下,不需要终结器。您可能需要在http://msdn.microsoft.com/en-us/library/system.object.finalize.aspx上阅读有关finalizer的内容,并注意

终止器执行的确切时间未定义。确保确定性释放类实例的资源,实现Close方法或提供IDisposable。处理实现。

你可能还想阅读理解何时在。net类中使用终结器,并注意:

为什么Finalize方法不好?

如果一个对象有终结器,它将被放置在FinalizationQueue中并且是subject这是一些额外的清理工作。一旦对象不再被线程或从全局引用中,垃圾收集器(GC)下次运行时,它将看到这个对象已准备好被收集。但它还不能收集。它必须让首先运行终结器。因此GC将完成收集,然后Finalizer将完成Finalize

这可能会对性能产生巨大影响,因为您应该记住所有管理线程将停止等待GC,然后GC将停止等待终结器线程。

还有很多关于finalize的数据,所以我鼓励你去阅读它尽可能多,这样你就能以最好的方式使用它。

如果你的对象需要一些确定性的东西,你可以实现IDisposable并显式调用Dispose()或使用using块:

using ( Character foo = CharacterFactory.CreateInstance("Jane") )
{
   // do something useful with Jane
}

当封闭的using块退出时,保证会调用foo.Dispose()。它与下面的代码完全相同(除了foo的作用域):

Character foo = ... ;
try
{
  ...
}
finally
{
  foo.Dispose() ;
}

然而,IDisposable的重点更多的是确保非托管资源被及时释放。当您的对象超出作用域并挂起等待GC时,阻塞了400个用户,导致正在运行的查询时,dba往往会变得非常暴躁。或者你的对象超出作用域,留下一个独占锁定的文件打开。

在c#中,对于希望被继承的抽象类使用虚析构函数是必要的还是标准的?

在c#中通常不会使用任何析构函数。它们可能随时被垃圾收集器调用,也可能不被调用(也可能不被调用)。

当您需要确定性清理时,实现IDisposable接口,并使用using块来清理(例如,非托管资源)。

析构函数不能被继承或重载。相关stackoverflow线程的详细信息:c#中的继承和析构函数