1

我有一些类通过 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 运行中被清理了。

再次感谢所有提供帮助的人!

4

6 回答 6

3

如果对 A 类的引用已死,您的 B 类将是 GC

于 2009-11-30T03:14:46.943 回答
1

我从不从这本字典中删除它们,但由于某种原因,B 类的析构函数被调用

.NET 中的析构函数与 C++(非托管)中的析构函数不同。
析构函数自动调用Finalize方法。

以下是析构函数的一些特征:

  • 析构函数不能在结构中定义。它们仅与类一起使用。
  • 一个类只能有一个析构函数。
  • 析构函数不能被继承或重载。
  • 不能调用析构函数。它们被自动调用
  • 析构函数不接受修饰符或参数。

所以你的情况是这样的(用两个词):

  1. A 类是垃圾收集。
  2. 由于 1:_particles 字段得到 GC-d。
  3. 由于 2: 字典中的条目变得无根(可用于垃圾收集)。
  4. 由于 3:字典中的条目(B 类实例)是 GC-d。

这可能与 Dictionary 类如何添加新引用有关吗?

不。

于 2009-11-30T03:27:50.097 回答
1

听起来你做错了什么。在托管环境中,像这样保留一个基本上将永远存在的引用相当于内存泄漏,除非您真的打算保留这些对象。

这里要记住的另一件事是,C# 中没有析构函数这样的东西。你所拥有的是finalizers,它们是不同的。托管代码很少需要编写终结器。这样做的唯一充分理由是,当您为类型实现 IDisposable 以包装尚未被终结器覆盖的非托管资源时

例如,许多人创建了一个实现 IDisposable 并将 SqlConnection 包装为数据访问层的一部分的类型。这样,他们可以在 using 块中包装该类型的实例,并确保他们创建的任何 SqlConnections 都被正确处理。但是这种类型不需要终结器,因为底层的数据库连接已经被 SqlConnection 类本身的终结器覆盖了。无需担心的非托管资源类型,只需担心 SqlConnection 类型。但是,如果您正在构建一个全新的数据库引擎并为其实现新的 .Net 数据提供程序,您可能希望为您的连接实现一个终结器。

于 2009-11-30T03:56:28.667 回答
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() 在某一时刻被调用了吗?这是怎么回事?

于 2009-11-30T03:44:06.150 回答
0

好的,谢谢大家的回答,我现在对GC和解构器当然有了很大的了解。

但问题是我自己的,我只在它不存在的情况下添加 someInt 并且通过有缺陷的业务逻辑, someInt 始终为 1,所以第一次通过它工作并且解构器没有被调用。但是第二次,“b”实例根本没有添加到列表中,而是在 GC 运行中被清理了。

我回答这个只是为了关闭它:)

于 2009-12-10T03:02:50.437 回答
-2

我会把我的钱押B在其他地方创建的课程上。如果是控制台应用程序,则在B构造函数和终结器中输出一些内容。确保实例化的数量符合您的预期。

于 2009-11-30T03:40:30.277 回答