C# Lambda闭包还是类级变量?

C# Lambda闭包还是类级变量?,c#,lambda,closures,variable-declaration,C#,Lambda,Closures,Variable Declaration,只是一个关于最佳实践是什么的一般性问题: public void Foo() { int x = 5; myControl.Click += (o, e) => { x = 6; }; } 注意,我正在lambda事件处理程序中使用x变量 或: 这里,x是类的私有成员,因此我可以在事件处理程序中访问它 现在让我们假设我不需要代码中的任何其他地方(无论出于何种原因),哪种方法是更好的方法?如果你在代码中的任何地方都不需要x,那么你的处理程序是

只是一个关于最佳实践是什么的一般性问题:

public void Foo()
{
    int x = 5;
    myControl.Click += (o, e) =>
    {
        x = 6;
    };
}
注意,我正在lambda事件处理程序中使用
x
变量

或:

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


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

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


一旦您确实需要x,您就需要决定是将其范围限定到Bar实例还是委派实例(或者可能是委派的某个集合),这将决定您要做什么。

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

也就是说,通常最好像对待变量一样对待事件处理程序(在代码中创建)。尽可能缩小它们的范围,并根据需要将它们重构到更大的范围

下面是一个更好的示例,突出显示了何时应该使用闭包:

public void Subscribe(Action<string> messageCallBack)
{
    myButton.Click += () => messageCallBack("Button was clicked.");
}
public void Subscribe(Action messageCallBack)
{
myButton.Click+=()=>messageCallBack(“按钮被点击”);
}
这允许多个订户,并且比备选方案简单得多:

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);
}
私有只读列表回调;
公共MyClass()
{
回调=新列表();
myButton.Click+=myButton\u Click;
}
私有myButton_单击(对象发送者,事件参数e)
{
foreach(回调中的操作回调)
{
回调(“点击按钮”);
}
}
公共无效订阅(操作消息回调)
{
callBacks.Add(messageCallBack);
}

我不习惯这种结束的方式,我想我不明白。。。在第一种方法中,当myControl.Click被触发并且范围中没有x(Foo()已返回)时会发生什么?在后台发生的事情是创建一个私有类,并将x作为实例变量。在本例中,x被复制到私有类。没有副作用,因为x是方法的局部范围。
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);
}