【问题标题】:Are anonymous methods defined inline?匿名方法是内联定义的吗?
【发布时间】:2013-06-11 04:45:03
【问题描述】:

匿名方法是内联定义的吗?在下面的示例中,委托对象“d”引用了一个匿名方法,该方法正在访问 Fun 方法中定义的“x”变量。 "x" 的作用域应该限制在 Fun 方法中,但是当我们调用 MyFun 时,它会调用作为参数传递的委托并递增 "x" 的值。

输出结果是“6”,这是怎么发生的? “x”的值,或者首先是“x”变量本身如何在匿名方法中可用?

public delegate void Del();

public void Fun()
{
    int x = 5;
    Del d = delegate { x++;  };
    MyFun(d);
    Console.WriteLine(x);
}

public static void MyFun(Del d)
{
    d();
}

【问题讨论】:

    标签: c# .net delegates scope anonymous-function


    【解决方案1】:

    这称为Closure。它捕获x 并在代理执行后立即使用它。这是通过一些编译器魔法完成的。

    不过,有时可能会令人困惑。例如,如果您在定义委托后更改 x,则将使用该更改值。

    【讨论】:

    • 什么时候捕获x
    • 详情请使用您喜欢的搜索引擎。除此之外 - 当委托分配给 d 时会捕获一个引用,但将使用执行时的当前值(参见答案的第二部分)。
    【解决方案2】:

    匿名方法是内联定义的吗?

    我不知道“内联”是什么意思。

    在下面的示例中,委托对象“d”引用了一个匿名方法,该方法正在访问 Del 方法中定义的“x”变量。

    不,x 是在 Fun 方法中定义的。 Del 不是方法,它是委托类型。

    “x”的范围应该限制在 Fun 方法中。

    正确。回想一下,“x 的范围”被定义为“可以通过其非限定名称查找 x 的程序文本区域”。您正确使用了该术语; Fun 的主体是x 的范围。请注意,匿名方法在 Fun 内部,因此 x 在范围内。

    当我们调用 MyFun 时,它会调用作为参数传递的委托并递增“x”的值。

    正确。

    输出结果为“6”。

    正确。

    这是怎么发生的?

    这个问题并不完全清楚。听起来您已经解释了这是如何发生的:变量x 在匿名函数的范围内,函数递增变量,因此变量的值发生了变化。

    如果您的问题是“编译器会生成什么代码来实现这一点?”编译器假装你写了这样的东西:

    public delegate void Del();
    
    private class Locals
    {
        public int x;
        public void AnonymousMethod() { x++; }
    }    
    
    public void Fun()
    {
        Locals locals = new Locals();
        locals.x = 5;
        Del d = locals.AnonymousMethod;
        MyFun(d);
        Console.WriteLine(locals.x);
    }
    
    public static void MyFun(Del d)
    {
        d();
    }
    

    【讨论】:

    • Eric,这在单个变量“x”的情况下看起来很简单。当我们从匿名方法中的某个对象“z”访问“x”和“y”时,编译器会生成什么?根据我们在匿名方法中访问的变量和对象的数量,这可能会变得很疯狂。
    • @Brij:这是一个问答网站。我的建议是您提出这个问题,有人会回答。
    • @Brij:是的,正如你所说,它可以“发疯”。如果您有嵌套匿名函数,这些函数使用外部函数的形式参数作为内部函数中的捕获变量,事情会变得特别复杂。这是编译器中比较棘手的部分之一。
    猜你喜欢
    • 2017-03-03
    • 1970-01-01
    • 2013-02-22
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2010-11-10
    • 2013-04-06
    • 1970-01-01
    相关资源
    最近更新 更多