c# - 为什么 C# 编译器生成单个类来捕获多个 lambda 的变量?

标签 c#

假设我们有这样的代码:

public class Observer
{
    public event EventHandler X = delegate { };
}

public class Receiver
{
    public void Method(object o) {}
}

public class Program
{
    public static void DoSomething(object a, object b, Observer observer, Receiver r)
    {
        var rCopy = r;
        EventHandler action1 = (s, e) => rCopy.Method(a);
        EventHandler action2 = (s, e) => r.Method(b);
        observer.X += action1;
        observer.X += action2;
    }

    public static void Main(string[] args)
    {
        var observer = new Observer();
        var receiver = new Receiver();
        DoSomething(new object(), new object(), observer, receiver);
    }
}

这里 action1action2 完全分离了一组捕获的变量 - rCopy 是专门为此创建的。尽管如此,编译器只生成一个类来捕获所有内容(选中生成的 IL)。我想这样做是出于优化原因,但它允许非常难以发现的内存泄漏错误:如果 ab 在单个类中捕获,则 GC 无法收集至少只要 任何 的 lambda 被引用。

有没有办法说服编译器生成两个不同的捕获类?或者有什么原因不能完成?

附言更详细一些,在我的博客中:herehere .

最佳答案

您重新发现了在 C# 中实现匿名函数的一个已知缺点。 I described the problem in my blog in 2007.

Is there a way to convince compiler to produce two different capture classes?

没有。

Or any reason why it cannot be done?

理论上没有理由可以设计出一种改进的算法来划分封闭变量,以便将它们提升到不同的封闭类中。出于实际原因,我们没有这样做:算法很复杂,正确和测试的成本很高,而且我们一直有更高的优先级。希望 Roslyn 会改变这种情况,但我们不做任何保证。

关于c# - 为什么 C# 编译器生成单个类来捕获多个 lambda 的变量?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/12009309/

相关文章:

c# - 信息标签

c# - Xamarin Forms - 更新标签值

c# - 有没有办法告诉 resharper 忽略整个解决方案的特定方法名称?

c# - 根据 Visual Studio 2010,jQuery 函数 "undefined"

C# - 动态参数是否装箱

C# SubmitChanges 不起作用

c# - 如何将字符串的特定字符解析为整数?

c# - 在 C# Windows 应用程序中查找打开的表单

C# Regex 匹配不包含特定字符串的字符串?

c# - 使用 ContinueWith 或 Async-Await 时的不同行为