gpt4 book ai didi

c# - 我可以在终结器中安全地访问引用类型实例字段/属性吗?

转载 作者:太空狗 更新时间:2023-10-29 17:51:59 27 4
gpt4 key购买 nike

我一直认为这个问题的答案是否定的,但我找不到任何资料表明这一点。在我下面的类(class)中,我可以在终结器中访问(托管)C 实例的字段/属性,即在 ReleaseUnmanaged() 中吗?有什么限制,如果有的话? GC 或终结是否会将这些成员设置为空?

我唯一能找到的是终结器队列中的东西可以按任何顺序终结。所以在那种情况下,因为 recommendation是类型应该允许用户多次调用 Dispose(),为什么推荐的模式使用 disposing boolean?如果我的终结器调用 Dispose(true) 而不是 Dispose(false) 会发生什么坏事?

public class C : IDisposable
{
private void ReleaseUnmanaged() { }

private void ReleaseOtherDisposables() { }

protected virtual void Dispose(bool disposing)
{
ReleaseUnmanaged();
if (disposing)
{
ReleaseOtherDisposables();
}
}

~ C()
{
Dispose(false);
}

public void Dispose()
{
Dispose(true);
GC.SuppressFinalize(this);
}
}

最佳答案

在一般情况下 - 是的,你可以。如果一个类有非空的终结器,第一次 GC 收集这个类的实例时,它会调用终结器(只有当你之前没有调用 GC.SuppressFinalize 时)。从终结器中看到的对象实例看起来就像您上次触摸它时一样。您甚至可以创建从根目录到您的实例的新(直接或间接)链接,因此 resurrect

即使您持有指向未固定对象的非托管指针并检查原始内存内容,您也不应该能够看到部分释放的对象,因为 .NET 使用复制 GC。如果一个实例在收集期间还活着,它要么被提升到下一代,要么与其他实例一起移动到全新的内存块。如果它不可访问,它要么留在原来的位置,要么释放整个堆并返回给操作系统。但是请记住,终结器可以而且将会在构造失败的对象实例上调用(即在对象构造过程中何时抛出异常)。

编辑:至于 Dispose(true)Dispose(false) 在编写良好的类中,从长远来看应该没有太大区别。如果您的终结器调用了 Dispose(true),它只会删除从您的对象到其他对象的链接,但由于您的对象已经不可访问,因此释放您的对象引用的其他实例不会影响它们的可访问性。

有关 .NET GC 实现细节的更多详细信息,我推荐 C# 5.0 in a Nutshell约瑟夫和本·阿尔巴哈里 (Joseph and Ben Albahari)。

关于c# - 我可以在终结器中安全地访问引用类型实例字段/属性吗?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/20167139/

27 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com