我知道c#中的析构函数没有执行顺序。
我在几个类中使用以下结构,它是为了破坏实例和静态信息:
public class MyClass
{
private static readonly Destructor DestructorObject = new Destructor();
~MyClass()
{
Console.WriteLine("Destructor Called");
}
static void Main(string[] args)
{
var myClass = new MyClass();
}
private sealed class Destructor
{
~Destructor()
{
Console.WriteLine("Static Destructor Called");
}
}
}
正如我上面提到的,析构函数的顺序是未定义的。但当我在许多类中使用此构造时,我发现每个类中都有一个不变的顺序,即使我重新编译应用程序并再次运行它,该顺序也仍然存在。
意味着一个MyClass1
总是可以运行~MyClass1
第一堂课和另一堂课MyClass2
可以一直跑吗~Destructor
first.
由于每个班级显然都有一个“隐藏”订单,我可以相信它吗?
由于每个班级显然都有一个“隐藏”订单,我可以相信它吗?
不,你不能。如果你看一下the docs https://msdn.microsoft.com/en-us/library/system.object.finalize%28v=vs.110%29.aspx,他们尖叫:
两个对象的终结器是不保证在任何环境中运行
具体订单,即使一个对象引用另一个对象。也就是说,如果
对象 A 具有对对象 B 的引用,并且两者都有终结器、对象
当对象 A 的终结器完成时,B 可能已经被终结
开始。
依赖这样的实现细节作为正常执行流程的一部分将是一个非常糟糕的主意。
看到由于某种原因您选择使用终结器作为清理静态资源的方式,您应该首先考虑这是否是正确的方法,考虑到析构函数所暗示的一切 https://stackoverflow.com/a/4899622/1870803, 进而at least实施IDisposable
并给调用者一个机会来处理资源,调用GC.SupressFinalize
以及。
在对象中使用此作为常见方法还会导致对象延长其生命周期,因为只有在移动到 f-reachable 队列后,它们才有资格被收集,并依赖终结器线程来实际清理它们,这根本无法保证。
埃里克·利珀特 (Eric Lippert) 最近 (18-05-2015) 开始了一个名为当你所知道的一切都是错误的 http://ericlippert.com/2015/05/18/when-everything-you-know-is-wrong-part-one/谈论终结器神话,我建议你看一下。
Edit:
有趣的是,埃里克斯第二篇文章 http://ericlippert.com/2015/05/21/when-everything-you-know-is-wrong-part-two(今天发布)在该系列中回答了这个问题:
误区:终结器以可预测的顺序运行
假设我们有一个对象树,所有对象都是可终结的,并且都在终结器队列上。不要求树从根到叶、从叶到根或任何其他顺序完成。
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)