C#Action,Closure和Garbage Collection

Pau*_*ich 15 c# closures garbage-collection

我是否需要将MyAction设置为null,以便垃圾收集能够继续使用这些类中的任何一个?

当两个班级的生命周期几乎相同时,我不太关心.当Class1的寿命比Class2长得多或者Class2的寿命比Class1长得多时,我的问题更合适.

这里的代码被删除了.假设Class1和Class2都包含可能影响其生命周期的其他成员和方法.

public class Class1 : IDisposable
{
    public Action<string> MyAction { get; set; }

    // Is this necessary?
    public void Dispose()
    {
        MyAction = null;
    }
}

public class Class2
{
    string _result = string.Empty;

    public void DoSomething()
    {
        Class1 myClass1 = new Class1();
        myClass1.MyAction = s => _result = s;
        myClass1.Dispose();
    }
}
Run Code Online (Sandbox Code Playgroud)

Eri*_*ert 19

我是否需要将MyAction设置为null,以便垃圾收集能够继续使用这些类中的任何一个?

不会.任何时候你"管理"托管资源,你可能做错了.让垃圾收集器完成它的工作.

当两个班级的生命周期几乎相同时,我不太关心.当Class1的寿命比Class2长得多或者Class2的寿命比Class1长得多时,我的问题更合适.

这个问题没有任何意义; 班级没有生命.存储位置具有使用寿命.准确地说,您担心哪些存储位置?你能澄清一下这个问题吗?

我注意到,通过闭包延长封闭变量的寿命存在非常严重的问题; 然而,你的问题是如此模糊,以至于很难理解你是否遇到了这样的情况.让我来证明:

class Expensive
{
    public byte[] huge = MakeHugeByteArray();
}

class Cheap
{
    public int tiny;
}

class C
{
    public static Func<Cheap> longLived;
    public static void M()
    { 
        Expensive expensiveLocal = new Expensive();
        Cheap cheapLocal = new Cheap();
        Func<Expensive> shortLived = ()=>expensiveLocal ;
        C.longLived = ()=>cheapLocal;
    }
}
Run Code Online (Sandbox Code Playgroud)

本地变量expensiveLocal的生命周期是多少?局部变量的生命周期通常很短 ; 通常局部变量不会超过方法激活.但是,处于闭包中会将局部变量的生命周期任意延长到闭包的生命周期.在这种特殊情况下,两个lambdas 共享一个闭包,这意味着局部变量expensiveLocal的生命周期至少与局部变量cheapLocal的生命周期一样长,因为对闭包的引用刚刚被存储,所以它具有无限长的生命周期.在一个永生的静态领域.这个大字节数组可能永远不会被回收,尽管很久以前就收集了似乎引用它的唯一东西; 闭包是一个隐藏的参考.

许多语言都有这个问题; C#,VB,JScript等都有词法闭包,这些闭包没有按生命周期分组到变量组.我们正在考虑改变C#和VB,以便对闭包进行更好的生命周期管理,但这是当前的远期工作,所以不能保证.

  • @Konstantin:好主意.我在2007年写了那篇文章:http://blogs.msdn.com/b/ericlippert/archive/2007/06/06/fyi-c-and-vb-closures-are-per-scope.aspx (3认同)
  • 好的,现在我尝试编译你的代码,我发现C#确实为两个闭包生成了一个类型,并且在"M"中只创建了一个这种类型的实例.廉价和昂贵的当地人都成为这种类型/实例的领域,巨大的阵列变得不朽!这太出乎意料了.现在,我以完全不同的方式理解您对编译器保证/规则的理论解释.我可以谦卑地提出这个作为你伟大博客帖子的主题吗?我想很多人会很惊讶:) (2认同)