Lambda闭包或类级变量?

时间:2009-01-08 15:46:30

标签: c# lambda closures variable-declaration

关于最佳做法是什么的一般性问题:

public void Foo()
{
    int x = 5;
    myControl.Click += (o, e) =>
    {
        x = 6;
    };
}

注意,我在lambda事件处理程序中使用x变量。

OR:

public class Bar
{
    private int x = 5;
    public void Foo()
    {
        Control myControl = new Control();
        myControl.Click += new EventHandler(myControl_Click);
    }

    private void myControl_Click(object sender, EventArgs e)
    {
        x = 6;
    }
}

这里,x是该类的私有成员,因此我可以在我的事件处理程序中访问它。

现在假设代码中的其他任何地方都不需要x(无论出于何种原因),哪种方法更好?

2 个答案:

答案 0 :(得分:3)

这取决于您的需要。在第一个示例中,事件处理程序的副作用仅限于方法范围,而在第二个示例中,副作用是实例作用域。我认为根据你的第一个例子使用闭包没有任何意义,因为X没有在任何地方使用,所以根据你的例子很难确定。

话虽这么说,通常最好将事件处理程序(您在代码中创建)视为变量。尽可能缩小范围,并根据需要将它们重构到更广泛的范围。

使用闭包时突出显示的更好示例如下:

public void Subscribe(Action<string> messageCallBack)
{
    myButton.Click += () => messageCallBack("Button was clicked.");
}

这允许多个订阅者,并且比其他订阅者简单得多:

private readonly List<Action<string>> callBacks;
public MyClass()
{
    callBacks = new List<Action<string>>();
    myButton.Click += myButton_Click;
}

private myButton_Click(object sender, EventArgs e)
{
    foreach (Action<string> callBack in callBacks)
    {
        callBack("Button was clicked");
    }
}

public void Subscribe(Action<string> messageCallBack)
{
    callBacks.Add(messageCallBack);
}

答案 1 :(得分:1)

如果你在代码中的任何其他位置都不需要x,那么你的处理程序就是无操作 - 所以肯定这是一个无意义的情况。

一旦你需要x,你需要决定它是否应该限定为Bar实例或委托实例(或者可能是一些代理集合),这将决定你做什么。