抽象类的析构函数

妖怪

在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#制作虚拟析构函数的方法?

尼古拉斯·凯里(Nicholas Carey)

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

GC将在清理垃圾回收对象实例时以及何时清理垃圾。当应用程序域终止时,所有对象都会[最终]被清除,但是给定对象可能会在应用程序域的整个过程中徘徊。在您的情况下,您不需要执行任何操作,因为您的对象没有需要清理的资源。当GC将其清除后,未引用的对象将得到正确处理。

通常,不需要终结器。您可能想在http://msdn.microsoft.com/zh-cn/library/system.object.finalize.aspx上阅读Finalizer,并注意:

终结器执行的确切时间是不确定的。为确保确定释放类实例的资源,请实现Close方法或提供IDisposable.Dispose实现。

您可能还需要阅读.NET类中的理解何时使用终结器的注意事项:

为什么Finalize方法不好?

...

如果对象具有终结器,则将其放置在FinalizationQueue中,并对其进行处理,以便进行其他一些清理。一旦不再在线程上或从全局引用中引用该对象,下一次垃圾收集器(GC)运行时,它将看到该对象已准备好被收集。但是它还不能收集它。它必须让终结器首先运行。因此,GC将完成收集,然后终结器将终结该对象,然后将进行另一个GC收集。

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

关于Finalization的信息很多,因此我鼓励您尽可能多地阅读有关Finalization的信息,以便您以最佳方式使用它。

如果您的对象需要确定性的东西,则可以实现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往往会变得脾气暴躁,从而使运行中的查询保持运行状态。否则,对象将超出范围,从而使独占锁定的文件保持打开状态。

本文收集自互联网,转载请注明来源。

如有侵权,请联系 [email protected] 删除。

编辑于
0

我来说两句

0 条评论
登录 后参与评论

相关文章