微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

c# – 使用BackgroundWorker的Lambda

为什么以下语法有效?

BackgroundWorker bw = new BackgroundWorker();
String one = resultFromSomeMethod();
String two = resultFromOtherMethod();
String three = resultFromThirdMethod();
bw.DoWork += (a,b) => TestMethod(one,two,three);

其中TestMethod定义为:

private void TestMethod(String one,String two,String three){
   //Do Stuff!!
}

DoWorkEventHandler被定义为一个委托,它接受两个参数:object sender和EventArgs e.但是,上面的TestMethod没有这样的参数.通过我对委托的理解,要创建一个新的委托,该方法必须符合委托的声明.我似乎通过使用lambda绕过了这个限制.上面的语法如何以及为什么工作,即使我尝试创建一个新的DoWorkEventHandler(TestMethod),它肯定不会工作?

我在Lambda Expressions上阅读了Eric White的blog,但它似乎没有回答这个问题.

解决方法

让我为你澄清一下lambda:

(a,b) => TestMethod("","","");

翻译为:

private void AnonymousLambda(object a,EventArgs b)
{
    TestMethod("","");
}

lambda的语法是:

implicit method arguments => method body

隐式方法参数由方法分配给(或调用)的预期签名确定.因为您将此lambda表达式分配给DoWorkEventHandler委托,所以它会自动将a和b分别解释为对象和EventArgs.

在某些情况下,编译器无法推断lambda参数的隐式类型,因此您也可以明确地编写它们:

(object a,EventArgs b) => TestMethod("","");

所以你真的在你匿名创建的另一种方法体内调用你的TestMethod!而outer方法具有DoWorkEventHandler方法签名.

编辑

根据有关字符串变量的其他问题详细信息,编译器将在代码上创建一个闭包,以将变量包含在方法范围内.代码基本上成为一个新类,它将变量保存为私有字段,然后在调用中引用它们:

public class AnonymousClosureClass
{
    public void AnonymousLambda(object a,EventArgs b)
    {
        // Note the reference to the original class instance
        String one = originalClassReference.one;
        String two = originalClassReference.two;
        String three = originalClassReference.three;
        TestMethod(one,three);
    }
}

您的主要代码实际上变为:

BackgroundWorker bw = new BackgroundWorker();

// Note: these may become field members to remain visible to the closure class
String one = resultFromSomeMethod();
String two = resultFromOtherMethod();
String three = resultFromThirdMethod();

var closure = new AnonymousClosureClass();
bw.DoWork += closure.AnonymousLambda;

最后,值得注意的是,这根本不是实际生成的闭包代码的命名或外观.

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 [email protected] 举报,一经查实,本站将立刻删除。

相关推荐