use*_*041 12 c# inheritance destructor
根据这一点,它声明Destructors cannot be inherited or overloaded.在我的情况下,对于所有子类,析构函数将是相同的.这几乎告诉我,我必须在每个子类中定义相同的析构函数.我无法在基类中声明析构函数并使处理具有破坏性?说我有这样的事情:
class A
{
~A()
{
SomethingA();
}
}
class B : A
{
}
B b = new B();
Run Code Online (Sandbox Code Playgroud)
什么时候B被破坏,它的析构函数不会被调用?
Eri*_*ert 42
据此,它声明Destructors不能被继承或过载.
正确.析构函数不是可继承的成员,并且不是虚拟的,因此不能被覆盖.它们总是具有相同的签名,因此不会超载.
在我的例子中,对于所有子类,析构函数将是相同的.
您提出这样一个基本问题的事实告诉我,您不应该首先实现析构函数.正确实现析构函数是C#中最难做的事情之一,除了最微不足道的情况.为什么你认为你需要实现析构函数?
这几乎告诉我,我必须在每个子类中定义相同的析构函数吗?
一点都不.你是如何从析构函数不被继承的事实得出这个结论的?
我无法在基类中声明析构函数并使处理具有破坏性?
当然,这是一件明智的事情,只要你一开始就倾向于实现析构函数.
当B被破坏时,它的析构函数不会被调用?
那是不对的.
在我看来,你自己尝试的时间要少得多,而不是在这里提问并等待回应.
什么时候析构函数被调用?当变量超出范围时,它是否在垃圾收集中?
我之前的推测是正确的.在深入了解整个垃圾收集过程之前,您绝对不应该实现析构函数.例如,您认为变量在超出范围时收集的事实表明您不能深入理解这一点以编写正确的析构函数.
当收集器确定某个对象无法从gc根目录中访问时,该对象具有一个尚未被抑制的终结器,则该对象通过将其放置在终结队列上以由终结器线程进行服务来提升到下一代.如果没有,它的内存将被回收.
当终结器线程开始运行时,它会运行对象的所有析构函数.(析构函数将按照从大多数派生到最少派生的顺序运行.)在该过程之后,对象可能会或可能不会无法访问,并且可能会或可能不会抑制终结.如果确定该对象不可达,则整个过程再次开始.
我无法强调你需要多少了解GC过程才能正确地完成这一过程.当你编写析构函数时,它会在没有任何意义的环境中运行.对象中的所有引用可能是仅由终结器队列生根的对象; 通常所有参考都是为了生活.引用可能是已经完成的对象.析构函数在不同的线程上运行.即使构造函数失败,析构函数也会运行,因此甚至可能无法正确构造对象.非原子值类型的字段可能只是部分写入 - 当线程被中止时,双字段完全有可能只有构造函数设置其四个字节; 终结器将看到部分写入的字段.即使对象因中止的事务而处于不一致状态,析构也会运行.等等.在编写析构函数时,你必须非常防守.
这个答案也可能有所帮助:
| 归档时间: |
|
| 查看次数: |
5124 次 |
| 最近记录: |