Lambda 闭包还是类级变量?

发布于 2024-07-11 15:04:57 字数 622 浏览 12 评论 0原文

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

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

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

或者:

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 (无论出于何种原因),哪种方法是更好的方法?

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.

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.

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?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

天暗了我发光 2024-07-18 15:04:57

这取决于您的需要。 在第一个示例中,事件处理程序的副作用仅限于方法范围,而在第二个示例中,副作用是实例范围的。 我认为在第一个示例中使用闭包没有任何意义,因为 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);
}

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.

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);
}
-黛色若梦 2024-07-18 15:04:57

如果您在代码中的其他任何地方都不需要 x,则您的处理程序是无操作的 - 所以这肯定是无意义的情况。

一旦您确实需要x,您需要决定它的作用域是否应该是Bar实例或委托实例(或者可能是一些委托集合),这将决定您要做什么。

If you don't need x anywhere else in the code, your handler is a no-op - so surely that's a nonsense situation.

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.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文