【问题标题】:memory management impact on setting objects to null in finally内存管理对最终将对象设置为 null 的影响
【发布时间】:2016-03-11 21:47:14
【问题描述】:
public void func1()
{    
    object obj= null;
    try
    {
             obj=new object();
    }
    finally
    {
             obj = null;
    }
}

在大对象的内存管理方面,将 null 分配给 finally 块中的引用有什么好处吗?

【问题讨论】:

  • 我在你的问题和标题之间找不到任何问题!
  • 标题是我的错。上面的问题是我原来的问题。我现在如何更改标题?
  • 使用问题下方的编辑按钮。
  • 您需要更明确地说明您正在谈论的对象类型。如果代码保持这种状态,那么 null 赋值就没用了。我们需要对象的范围(将存在多少)和某种方式来理解对象的属性(将使用多少内存,可以访问非托管资源,实现可处置...)
  • 看看Large object heap问题

标签: c# garbage-collection


【解决方案1】:

让我们在这里处理显式和隐式问题。

问:首先,当你完成一个局部变量时,将 null 分配给它有什么意义吗?

答:不,根本没有。当使用优化编译并且不在调试器下运行时,JITter 知道变量正在使用的代码段,并且当您通过该段时将自动停止将其视为根。换句话说,如果你给一个变量赋值,然后在某个时候不再读取它,即使你没有明确地将它设置为null,它也可能被收集。

所以你的例子可以安全地写成:

public void func1()
{    
    object obj = new object();
    // implied more code here
}

如果“此处隐含更多代码”中没有任何代码访问过obj 变量,则不再将其视为根。

请注意,如果在未优化的程序集中运行,或者如果您将调试器连接到进程,这会发生变化。在这种情况下,变量的范围会被人为地扩展至其范围的末尾,以便于调试。


问:其次,周边类的字段呢?

答:在这里绝对可以有所作为。

如果您的方法周围的对象在很长一段时间内保持活动状态,并且不再需要字段内容,那么是的,将字段设置为 null 将使其引用的旧对象符合条件收藏。

所以这段代码可能有优点:

public class SomeClass
{
    private object obj;

    public void func1()
    {    
        try
        {
             obj=new object();
             // implied more code here
        }
        finally
        {
             obj = null;
        }
    }
}

但是,你为什么要这样做呢?相反,您应该努力编写不依赖于周围状态的更简洁的代码。在上面的代码中,您应该重构“此处隐含更多代码”以在要使用的对象中传递,并删除全局字段。

显然,如果您不能这样做,那么可以,只要不再需要其对象引用,就将字段设置为 null 是个好主意。


有趣的实验,如果您在LINQPad 中运行以下代码并进行优化,您期望输出是什么?

void Main()
{
    var s = new Scary();
    s.Test();
}

public class Scary
{
    public Scary()
    {
        Console.WriteLine(".ctor");
    }

    ~Scary()
    {
        Console.WriteLine("finalizer");
    }

    public void Test()
    {
        Console.WriteLine("starting test");
        GC.Collect();
        GC.WaitForPendingFinalizers();
        GC.Collect();
        Console.WriteLine("ending test");
    }
}

Answer(鼠标悬停在您认为已掌握时显示):

.ctor
开始测试
终结器
结束测试

解释:

由于实例方法的隐式this 参数从未在方法内部使用,因此即使该方法当前正在运行,也会收集该方法周围的对象。

【讨论】:

    猜你喜欢
    • 2013-11-15
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2010-10-09
    • 1970-01-01
    • 1970-01-01
    • 2019-07-15
    相关资源
    最近更新 更多