代码之家  ›  专栏  ›  技术社区  ›  John

在.NET中使用后将对象设置为Null/Nothing

  •  177
  • John  · 技术社区  · 18 年前

    是否应将所有对象设置为 null ( Nothing

    我理解在.NET中,处理实现 IDisposable 接口来释放一些资源,尽管对象在被释放后仍然可以是某种东西(因此 isDisposed 属性),所以我假设它仍然可以驻留在内存中,或者至少部分驻留在内存中?

    我还知道,当一个对象超出作用域时,它会被标记为准备收集,以便下一次通过垃圾收集器(尽管这可能需要时间)。

    因此,考虑到这一点,我们会将其设置为 加快系统释放内存的速度,因为它不必计算出内存已不在范围内,它们是否有任何不良副作用?

    MSDN文章从来没有在示例中这样做过,目前我做不到这一点 看到危害了吧。然而,我遇到了各种各样的意见,所以任何评论都是有用的。

    13 回复  |  直到 7 年前
        1
  •  73
  •   erlando    7 年前

    Karl是绝对正确的,使用后无需将对象设置为null。如果对象实现 IDisposable ,一定要打电话 IDisposable.Dispose() 当你处理完这个对象(用 try .. finally using() 块)。但即使你不记得打电话 Dispose() 处置 为你。

    我认为这是一种很好的治疗:

    Digging into IDisposable

    Understanding IDisposable

    试图对GC及其管理策略进行二次猜测是没有任何意义的,因为它是自调优和不透明的。与Jeffrey Richter在Dot Net Rocks上就内部工作进行了很好的讨论: Jeffrey Richter on the Windows Memory Model 和 里希特书 CLR via C# 第20章有一个很好的论述:

        2
  •  37
  •   Wilka    18 年前

    例如

    void foo()
    {
        var someType = new SomeType();
        someType.DoSomething();
        // someType is now eligible for garbage collection         
    
        // ... rest of method not using 'someType' ...
    }
    

    将允许在调用“DoSomething”后对someType引用的对象进行GC'd,但是

    void foo()
    {
        var someType = new SomeType();
        someType.DoSomething();
        // someType is NOT eligible for garbage collection yet
        // because that variable is used at the end of the method         
    
        // ... rest of method not using 'someType' ...
        someType = null;
    }
    

    有时可能会使对象保持活动状态,直到方法结束。这个 JIT will usually optimized away the assignment to null

        4
  •  7
  •   dbkk    18 年前

    一般来说,使用后不需要空对象,但在某些情况下,我发现这是一种很好的做法。

    如果一个对象实现IDisposable并存储在一个字段中,我认为最好将其设为null,以避免使用disposed对象。以下类型的错误可能会令人痛苦:

    this.myField.Dispose();
    // ... at some later time
    this.myField.DoSomething();
    

        5
  •  7
  •   mbillard    18 年前

    如果您觉得有必要,代码的结构可能不够紧密 null

    有许多方法可以限制变量的范围:

    如 史蒂夫·特兰比

    using(SomeObject object = new SomeObject()) 
    {
      // do stuff with the object
    }
    // the object will be disposed of
    

    {
        // Declare the variable and use it
        SomeObject object = new SomeObject()
    }
    // The variable is no longer available
    

    我发现使用不带任何“标题”的花括号可以真正清理代码并使其更易于理解。

        6
  •  6
  •   Steve T    18 年前

    using(SomeObject object = new SomeObject()) 
    {
      // do stuff with the object
    }
    // the object will be disposed of
    
        7
  •  5
  •   Bob    18 年前

    唯一应该将变量设置为null的时间是当变量未超出范围并且不再需要与之关联的数据时。否则就没有必要了。

        8
  •  5
  •   Munish Goyal    14 年前

    private void Reset()
    {
        if(_dataset != null)
        {
           _dataset.Dispose();
           _dataset = null;
        }
        //..More such member variables like oracle connection etc. _oraConnection
     }
    
        9
  •  3
  •   Siddharth Rout    14 年前

    这种“使用后无需将对象设置为null”的说法并不完全准确。在处理变量后,有时需要将其设为NULL。

    是的,你应该随时打电话 .Dispose() .Close() 当你做完的时候,在任何有它的东西上。无论是文件句柄、数据库连接还是一次性对象。

    假设我有并实例化了 ObjA 属于 class A Class A 有一个公共财产叫做 PropB 属于 class B .

    内部,, 道具 使用的私有变量 _B 默认为null。什么时候 PropB.Get() _PropB 为空,如果为空,则打开实例化 B 进入 _道具 . 然后它返回 _道具

    根据我的经验,这是一个非常有用的技巧。

    如果以某种方式重置或更改 _道具 是以前的价值观的产物 A ,则需要进行处置并清空 _道具 因此,如果代码需要,LazyLoad可以重置以获取正确的值。

    如果你愿意的话 _PropB.Dispose() Dispose() 只是想确定一下。

    在 在执行Dispose的调用函数之外(因此几乎超出范围),private prop仍然不是null,过时的数据仍然存在。

    最终,disposed属性将为null,但从我的角度来看,这是不确定的。

    dbkk提到的核心原因是父容器( 具有 )正在保留 _道具 .

        10
  •  1
  •   Patrick    18 年前

    在某些情况下,空引用是有意义的。例如,当您编写一个集合(如优先级队列)时,根据您的约定,在客户机将这些对象从队列中删除之后,您不应该为客户机保持这些对象的活动状态。

    总的来说,你真的不应该麻烦。让编译器和GC完成它们的工作,这样您就可以完成自己的工作。

        11
  •  1
  •   Scott Dorman    17 年前

    http://www.codeproject.com/KB/cs/idisposable.aspx

    在大多数情况下,将对象设置为null没有效果。只有在使用“大对象”时才应确保这样做,该对象的大小大于84K(如位图)。

        12
  •  1
  •   Ebleme    7 年前

    Should I Set Variables to Null to Assist Garbage Collection?

    说:

    简短的回答,对于不耐烦的人来说 是,如果变量是静态字段,或者您正在编写可枚举方法(使用yield-return)或异步方法(使用async和await)。否则,不会。

    我们应该考虑的重要事情是 静态场 .

    一直被认为是活着的 通过垃圾收集器。如果静态字段引用不再需要的对象,则应将其设置为null,以便垃圾收集器将其视为符合收集条件。

    如果整个进程正在关闭,那么将静态字段设置为null是没有意义的。此时将对整个堆进行垃圾收集,包括所有根对象。

    静态场 ; 就这样。其他任何东西都是错误的 浪费时间 .

        13
  •  0
  •   John    10 年前

    具有无效性的GC。我确信他们希望您不必担心GC运行的方式/时间——像这样对待它 存在

    就我个人而言,当我将变量作为一种自我文档的形式使用时,我经常显式地将它们设置为null。我不声明、使用,然后稍后设置为null——我在不再需要它们之后立即设置为null。我明确地说,“我和你正式结束了……走吧……”

    在GC'd语言中是否需要取消?不,这对GC有帮助吗?也许是的,也许不是,我不确定,从设计上来说,我真的无法控制它,不管今天这个版本的答案是什么,未来的GC实现可能会改变我无法控制的答案。另外,如果/当调零被优化时,它只不过是一种幻想 议论

    我想如果这能让下一个追随我脚步的可怜的傻瓜更清楚我的意图,如果 “可能”

    我是这样看待它的:编程语言的存在是为了让人们对意图有一个概念,让编译器对要做的事情有一个作业请求——编译器将该请求转换为CPU的另一种语言(有时是几种语言)——CPU可以告诉我们您使用的语言、选项卡设置、注释、风格重点,变量名,等等——CPU的所有功能都是关于位流,它告诉CPU要旋转的寄存器、操作码和内存位置。许多用代码编写的东西不会按照我们指定的顺序转换为CPU消耗的东西。我们的C、C++、C、LISP、Babel、汇编程序或其他什么是理论而不是现实,被写为工作语句。你看到的不是你得到的,是的,即使是在汇编语言中。

    我确实理解“不必要的东西”(如空行)“只不过是噪音和混乱的代码”的心态;我完全明白。在这一点上,我倾向于使代码更清晰。这不像我在我的程序中添加了50行“噪音”——这里或那里只有几行。

        14
  •  0
  •   Thulani Chivandikwa    7 年前

    我认为将某些内容设置回null是一件混乱的事情。设想一个场景,其中设置为now的项通过属性公开。在某种程度上,您需要在某个属性上意外地使用null来处理某个异常,然后才能得到该属性的某个引用。

        15
  •  -1
  •   T.S.    9 年前

    一些物体假设 .dispose()