有人可以解释在对象超出范围之前将对象置零的意义吗?

时间:2011-03-07 17:44:04

标签: c# .net garbage-collection

我在几个地方看到了具有以下逻辑的代码:

public void func()
{
   _myDictonary["foo"] = null;
   _myDictionary.Remove("foo");
}

在删除字典之前将字典中的foo设置为null有什么意义?

我认为垃圾收集关心指向* foo最初的东西的数量。如果是这种情况,不将myDictonary [“foo”]设置为null只是将计数减少一个?一旦myDictonary.Remove(“foo”)被调用,会不会发生同样的事情?

_myDictonary [“foo”] = null;

的重点是什么?

编辑:澄清 - 当我说“删除一个计数”时,我的意思如下:
- myDictonary [“foo”]最初指向一个对象。这意味着该对象有一个或多个引用它的东西 - 一旦myDictonary [“foo”]设置为null,它就不再引用所述对象。这意味着对象引用它的次数更少。

8 个答案:

答案 0 :(得分:13)

毫无意义。

如果你看一下Remove方法的作用(使用.NET Reflector),你会发现:

this.entries[i].value = default(TValue);

该行将字典项的值设置为null,因为引用类型的默认值为null。因此,当Remove方法将引用设置为null时,在调用方法之前没有必要这样做。

答案 1 :(得分:4)

将词典条目设置为null会使减少引用计数,因为null是一个非常适合在字典中指向的值。

这两个陈述做了很多不同的事情。将值设置为null表示该值应该是该键的值,而从字典中删除该键表示它不再存在。

答案 2 :(得分:4)

没有多大意义。

但是,如果Remove方法导致堆分配,并且存储的值很大,则在调用Remove时可能会发生垃圾回收,并且它还可以收集进程中的值(可能释放内存)。但实际上,人们通常不会担心这样的小事情,除非显示有用。


编辑:

忘记提及:理想情况下,字典本身应该担心它自己的实现,而不是调用者。

答案 3 :(得分:1)

那里没有多大意义,但有时它确实有意义。

一个例子是Dispose()方法。考虑这种类型:

public class Owner
{
    // snip

    private BigAllocation _bigAllocation;

    // snip

    protected virtual void Dispose(bool disposing)
    {
        if (disposing)
        {
            // free managed resources
            if (_bigAllocation != null)
            {
                _bigAllocation.Dispose();
                _bigAllocation = null;
            }
        }
    }
}

现在,你可以说这是不必要的,而且你大多数都是正确的。 通常 Dispose()仅在Owner被解除引用之前被调用,而当Owner被收集时,_bigAllocation也会被最终...

然而:

_bigAllocation设置为null会使其有资格立即收藏 ,如果没有其他人有引用它的话。如果Owner在更高编号的GC生成中,或者具有终结器,则这可能是有利的。否则,Owner必须在_bigAllocation有资格收集之前发布。

但这是一个极端的案例。大多数类型不应该有终结器,并且在大多数情况下_bigAllocationOwner将在同一代中。

答案 4 :(得分:0)

我想我可能会发现这在多线程应用程序中很有用,在这个应用程序中,您将对象置零,因此没有其他线程可以对其进行操作。虽然,这看起来很重,设计很差。

答案 5 :(得分:0)

  
    

如果是这种情况,则不会将myDictonary [“foo”]设置为null     只需将计数减少一个?

  

不,计数不会改变,引用仍然在字典中,它指向null。

我认为没有理由让代码成为现实。

答案 6 :(得分:0)

我特别不了解Dictionary的内部结构,但某些类型的集合可能会引用对有效“死”的对象。例如,集合可以包含数组以及数组中有效项的数量;将计数归零会使集合中的任何项目无法访问,但不会销毁对它们的任何引用。可能是从词典中删除项目最终使得保持该对象的区域可以重用而不实际删除它。如果另一个具有相同哈希码的项目被添加到字典中,那么第一个项目实际上会被删除,但如果有的话,这可能暂时不会发生。

答案 7 :(得分:0)

这看起来像是一个古老的C ++习惯。

我怀疑作者担心较旧的收藏品和/或其他语言。如果内存服务,C ++中的某些集合将保存指向所收集对象的指针,当'removed'只删除指针但不会自动调用新删除的对象的析构函数。这会导致非常微妙的内存泄漏。习惯是在删除对象之前将对象设置为null,以确保调用析构函数。