简体   繁体   English

Lambda闭包还是类级别变量?

[英]Lambda closure or class level variable?

Just a general question about what the best practice is: 关于最佳实践是一个普遍的问题:

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

Notice, I'm using the x variable inside my lambda event handler. 注意,我在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;
    }
}

Here, x is a private member of the class, and therefore I have access to it in my event handler. 在此, x是该类的私有成员,因此我可以在事件处理程序中访问它。

Now let's say I don't need x anywhere else in the code (for whatever reason), which method is the better way to go? 现在让我们说我不需要在代码的其他任何地方使用x (无论出于何种原因),哪种方法是更好的选择?

It depends on your need. 这取决于您的需要。 In the first example, the side-effects of your event handler are limited to method scope, and in the second, the side-effects are instance scoped. 在第一个示例中,事件处理程序的副作用仅限于方法范围,而在第二个示例中,副作用则在实例范围内。 I think that using a closure in terms of your first example serves no purpose since X isn't used anywhere, so it's hard to determine based on your examples. 我认为在第一个示例中使用闭包是没有用的,因为X并未在任何地方使用,因此很难根据示例来确定。

That being said, it is generally best to treat event handlers (that you create in code) as you would variables. 话虽如此,通常最好将事件处理程序(在代码中创建)与变量一样对待。 Scope them as narrowly as you can, and refactor them to broader scope as needed. 尽可能缩小范围,然后根据需要将它们重构为更大的范围。

A better example that highlights when you should use a closure is as follows: 突出显示何时使用闭包的更好示例如下:

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

This allows multiple subscribers, and is much simpler than the alternative: 这允许多个订户,并且比替代方案要简单得多:

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);
}

If you don't need x anywhere else in the code, your handler is a no-op - so surely that's a nonsense situation. 如果您在代码中的其他任何地方都不需要x,则您的处理程序为空操作-因此,这肯定是胡扯。

Once you do need x, you need to decide whether it should be scoped to the Bar instance or the delegate instance (or possibly some collection of delegates), and that will dictate what you do. 一旦确实需要x,就需要确定它的作用域是Bar实例还是委托实例(或可能是某些委托集合),而这将决定您的工作。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM