我有一些类通过IDictionary实例成员保存对其他类的引用。
像这样:
class A
{
private readonly Dictionary<int, B> _particles = new Dictionary<int, B>();
public void CreateNewB(int someInt)
{
var b = new B();
if (!_particles.ContainsKey(someInt)
_particles.Add(someInt, b);
}
}
所以这是设置,我永远不会从这个字典中删除它们,但由于某种原因,B类的析构函数会不时地在GC上运行,我不明白为什么。
这可能与Dictionary类如何添加新引用有关吗?
固定:
好的,谢谢大家的回答,我现在已经对GC和解构器有了很大的了解。
但是这个问题是我自己的,我只是添加了 someInt ,如果它已经不存在并且通过有缺陷的业务逻辑, someInt 总是1,所以第一次通过它工作,解构主义者没有得到调用。但第二次,“b”实例根本没有添加到列表中并在GC运行中被清理。
再次感谢所有帮助过的人!
答案 0 :(得分:3)
如果对A类的引用已经死亡,那么你的B级将是GC
答案 1 :(得分:1)
我永远不会从中删除它们 字典,但由于某种原因, B类的析构函数被称为
.NET中的析构函数与C ++中的析构函数(非托管函数)不同 析构函数自动调用Finalize方法。
以下是destructor的一些特征:
所以你的情况是这样的(用2个字):
这可能与如何做有关 Dictionary类添加了新的 引用?
没有
答案 2 :(得分:1)
听起来你做的事情非常错误。在托管环境中,保持像这样基本上永久存在的引用相当于内存泄漏,除非你真的想要保留这些对象。
这里要记住的另一件事是C#中没有析构函数这样的东西。你所拥有的是终结者,它们是不同的。托管代码很少见,甚至根本不需要编写终结器。这样做的唯一理由是,当您为类型实现IDisposable以包装未被终结器覆盖的非托管资源时。
例如,很多人创建了一个实现IDisposable的类型,并将SqlConnection包装为其数据访问层的一部分。这样,他们可以使用块包装该类型的实例,并确保他们创建的任何SqlConnections都正确处理。但是这种类型不需要终结器,因为底层数据库连接已经被SqlConnection类本身的终结器所覆盖。没有 new 非托管资源类型需要担心,只有SqlConnection类型。但是,如果您正在构建一个全新的数据库引擎并为其实现新的.Net数据提供程序,那么您可能希望为您的连接实现终结器。
答案 3 :(得分:0)
所以我有以下类型:
type k {
public k() { Console.WriteLine("Hi, I'm a new K!"); }
public ~k() { Console.WriteLine("I'm a dying K!"); }
}
还有一小段代码:
Dictionary<int, k> ks = new Dictionary<int, k);
for(int i=0;i<10;i++) { ks.add(i, new k()); }
你看到~k()被一次调用了?那是什么意思?
答案 4 :(得分:0)
好的,谢谢大家的回答,我现在已经对GC和解构器有了很大的了解。
但是这个问题是我自己的,我只是在它已经存在并且通过有缺陷的业务逻辑时添加someInt,someInt总是1,所以第一次通过它工作并且解构器没有被调用。但第二次,“b”实例根本没有添加到列表中并在GC运行中被清理。
我正在回答此事只是为了关闭它:)
答案 5 :(得分:-2)
我敢打赌我在其他地方创建的课程B
。如果它是一个控制台应用程序,则在B
构造函数和终结器中输出一些内容。确保实例化的数量符合您的预期。