【问题标题】:The scope of variable in inner anonymous method内部匿名方法中的变量范围
【发布时间】:2013-12-29 08:12:14
【问题描述】:

查看代码

public class Test
{
    public static void Main()
    {
        Test t = new Test();
        var AnonymousMethod = t.OuterMethod();
        AnonymousMethod("passedValue");
    }
     public delegate void SampleDelegate(string InputText);

     public SampleDelegate OuterMethod()
    {
        string outerValue="outerValue";
        return (x => {
            Console.WriteLine(x);
            Console.WriteLine(outerValue);
        });

    }
}

输出

Success  time: 0.02 memory: 33816 signal:0
passedValue
outerValue

链接到Example

通常变量outerValue 的范围会在调用t.OuterMethod() 之后结束。但是在使用匿名类型的情况下,控制台清楚地打印了输出(Console.WriteLine(outerValue)),这意味着变量的范围没有结束。编译器实际上做了什么来确定它的范围?它会将Main 方法的范围分配给匿名方法中使用的变量吗?我知道如何使用,但不知道它是如何工作的。请指导我?

编辑

假设附加到事件的匿名方法。该事件可能是 稍后执行。然后变量将在内存中。仪式?如果 分配了很多事件,大量内存!我想这是一件坏事。 我有没有搞错?

【问题讨论】:

  • 变量被编译成一个闭包,供匿名方法使用和保存。
  • @AdamHouldsworth 那么关闭的范围?
  • 查看 Jon Skeet 的回答 :-)

标签: c# oop closures


【解决方案1】:

变量的范围(程序文本的区域,可以在其中不加限定地引用它)保持不变。

变量的“生命周期”得到有效延长:lambda 表达式捕获变量。编译器将为您生成一个私有嵌套类,其中包含该变量 - 方法和委托都引用此嵌套类的同一实例,并且该实例将不符合垃圾回收条件,直到该方法不再引用到它并且委托实例有资格进行垃圾回收。

【讨论】:

  • 假设附加到事件的匿名方法。该事件可能会在很久以后执行。然后变量将在内存中。仪式?如果分配了很多事件,就会占用大量内存!我想这是一件坏事。我有错吗?
  • 请也回答这个问题。
  • @SubinJacob:首先,在进一步提示之前,请让人们有机会与 cmets 联系。 Stack Overflow 不是您自己的私人仆人池。我们的生活还有其他事情要做。但是,是的,这可能是一个令人担忧的原因 - 但大概您只是捕获变量,因为您需要它们,这意味着这是您尝试做的事情的固有问题,而不是在C# 实现。 (如果多个匿名函数从同一作用域捕获不同的变量,那么在 C# 实现中存在一个问题,但这要复杂得多。)
  • 如果您有这种感觉,我深感遗憾。我不是这个意思。谢谢你的回答。
【解决方案2】:

匿名方法被编译成它们自己的类。这些类具有每个捕获变量的字段。类的实例是“范围”。

捕获了哪些变量?所有顶级符号。

例如。

Action a = () => this.ANumber;

this 被捕获。

int aNumber = this.ANumber;
Action a = () => aNumber;

仅捕获aNumber

【讨论】:

  • 有时会创建一个新类。但并非总是如此 - 这取决于是否有任何要捕获的变量。当只捕获this 时,我相信编译器只是为匿名函数创建了一个实例方法。
  • @JonSkeet 有道理。感谢您的知识 - 很高兴收到您的意见。
  • 假设附加到事件的匿名方法。该事件可能会在很久以后执行。然后变量将在内存中。仪式?如果分配了很多事件,就会占用大量内存!我想这是一件坏事。我有错吗?
  • @SubinJacob 捕获的变量的生命周期与您对事件订阅的预期相同。是的,你是对的。但请注意:除非您存储对 lambda 的引用,否则您可能无法取消订阅该事件!
猜你喜欢
  • 1970-01-01
  • 2012-05-18
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2010-10-22
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多