C#的行动,封闭,和垃圾收集 [英] C# Action, Closure, and Garbage Collection

查看:121
本文介绍了C#的行动,封闭,和垃圾收集的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我是否需要设置MyAction为null,使垃圾收集将能够与这两种类别的继续?



我较少关注当这两个类是具有几乎相同的寿命。我的问题是比较合适的,当1级的寿命要长得多则Class2中或当Class2中的寿命要长得多则1级。



下面的代码剥离下来。 。假设两个1级和Class2中包含其他成员和方法,可能会影响其寿命

 公共类的Class1:IDisposable的
{
公共动作<串GT; MyAction {搞定;组; }

//这个必要吗?
公共无效的Dispose()
{
MyAction = NULL;
}
}

公共类Class2中
{
串_result =的String.Empty;

公共无效DoSomething的()
{
Class1的MyClass1的=新1级();
myClass1.MyAction = S = GT; _result =秒;
myClass1.Dispose();
}
}


解决方案

我是否需要设置MyAction为null,使垃圾收集将能够与这两种类别的继续?




没有。任何时候你托管资源的处置,赔率是好的,你做错了。让垃圾收集器做的工作。




我不太关注的时候这两个类都具有几乎相同的寿命。我的问题是比较合适的,当1级的寿命要长得多则Class2中或当Class2中的寿命要长得多则1级。




这个问题没有按'任何意义;的的没有的寿命的。 的存储位置都有寿命。正是其中的存储位置,你担心什么? ?你能澄清这个问题。



我注意到,大约有通过延长封闭了变量的寿命很严重关切;然而,你的问题是如此模糊,这是很难理解是否正在运行到如此境地。让我来演示:

 类昂贵的
{
公共字节[] =巨大MakeHugeByteArray();
}

类便宜
{
公众诠释微小的;
}

类C
{
公共静态Func键<&便宜GT;寿星;
公共静态无效的M()
{
昂贵expensiveLocal =新贵();
廉价cheapLocal =新低价();
Func键<&昂贵GT;短命=()=> expensiveLocal;
C.longLived =()=> cheapLocal;
}
}



什么是局部变量的生存expensiveLocal ?的局部变量的生存期通常是的;通常局部变量活得比方法激活不再。然而,在一个封闭是任意长的延伸局部变量的生存期,到了封闭的寿命。在这种特殊情况下,无论是lambda表达式的共享的封闭,而也就是说,局部变量expensiveLocal的寿命至少只要局部变量cheapLocal,因为应用于封闭的引用刚刚被存储在长存。这大字节数组可能的从不的回收,尽管这似乎引用它早就已经收集到的唯一的事情; ,闭包是一个隐藏的参考



许多语言都有这个问题; C#,VB,JScript和等都有不受一生划分为组变量词法闭包。我们正在考虑改变C#和VB中有关门,而是更好生命周期管理在这一点上远在最今后的工作,所以没有保证。


Do I need to set MyAction to null so that garbage collection will be able to proceed with either of these classes?

I am less concerned when both classes are to have almost the same lifespan. My question is more appropriate when Class1’s lifespan is much longer then Class2 or when Class2’s lifespan is much longer then Class1.

The code here is stripped down. Assume that both Class1 and Class2 contain other members and methods that may affect their lifespan.

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();
    }
}

解决方案

Do I need to set MyAction to null so that garbage collection will be able to proceed with either of these classes?

No. Any time you "Dispose" of a managed resource, odds are good you are doing it wrong. Let the garbage collector do its work.

I am less concerned when both classes are to have almost the same lifespan. My question is more appropriate when Class1’s lifespan is much longer then Class2 or when Class2’s lifespan is much longer then Class1.

The question doesn't make any sense; classes do not have lifetimes. Storage locations have lifetimes. Precisely which storage locations are you worried about? Can you clarify the question?

I note that there are very serious concerns about extending lifetimes of closed-over variables via closures; your question however is so vague that it is hard to understand whether you are running into such a situation. Let me demonstrate:

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;
    }
}

What is the lifetime of local variable expensiveLocal? The lifetime of a local variable is typically short; typically local variables live no longer than the method activation. However, being in a closure extends the lifetime of a local variable arbitrarily long, to the lifetime of the closure. In this particular case, both lambdas share a closure, and that means that the lifetime of local variable expensiveLocal is at least as long as the lifetime of local variable cheapLocal, which has an indefinitely long lifetime because a reference to the closure has just been stored in a static field that lives forever. That big byte array might never be reclaimed, even though the only thing that seems to reference it has been collected long ago; the closure is a hidden reference.

Many languages have this problem; C#, VB, JScript and so on all have lexical closures that are not partitioned to group variables by lifetime. We are considering changing C# and VB to have better lifetime management for closures but that is far-in-the-future work at this point, so no guarantees.

这篇关于C#的行动,封闭,和垃圾收集的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆