为什么以下语法有效?
BackgroundWorker bw = new BackgroundWorker();
String one = resultFromSomeMethod();
String two = resultFromOtherMethod();
String three = resultFromThirdMethod();
bw.DoWork += (a,b) => TestMethod(one, two, three);
Run Code Online (Sandbox Code Playgroud)
其中TestMethod定义为:
private void TestMethod(String one, String two, String three){
//Do Stuff!!
}
Run Code Online (Sandbox Code Playgroud)
它DoWorkEventHandler被定义为一个带有两个参数的委托:object sender和EventArgs e.但是,上面的TestMethod没有这样的参数.通过我对委托的理解,要创建一个新的委托,该方法必须符合委托的声明.我似乎通过使用lambda绕过了这个限制.上面的语法如何以及为什么工作,即使我尝试创建new DoWorkEventHandler(TestMethod)它肯定不会工作?
我阅读了Eric White 关于Lambda Expressions 的博客,但它似乎没有回答这个问题.
Han*_*ney 10
让我为你澄清一下lambda:
(a,b) => TestMethod("", "", "");
Run Code Online (Sandbox Code Playgroud)
翻译为:
private void AnonymousLambda(object a, EventArgs b)
{
TestMethod("", "", "");
}
Run Code Online (Sandbox Code Playgroud)
lambda的语法是:
implicit method arguments => method body
Run Code Online (Sandbox Code Playgroud)
隐式方法参数由方法分配给(或调用)的预期签名确定.因为你这个分配lambda表达式的DoWorkEventHandler委托,就自动地解释a,并b为object和EventArgs分别.
在某些情况下,编译器无法推断lambda参数的隐式类型,因此您也可以明确地编写它们:
(object a, EventArgs b) => TestMethod("", "", "");
Run Code Online (Sandbox Code Playgroud)
所以你真的在你匿名创建的另一种方法体内调用你的TestMethod!而外部方法有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, two, three);
}
}
Run Code Online (Sandbox Code Playgroud)
您的主要代码实际上变为:
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;
Run Code Online (Sandbox Code Playgroud)
最后,值得注意的是,这根本不是实际生成的闭包代码的命名或外观.
在TestMethod正在从(A,B)函数调用.
这样看是这样的:
BackgroundWorker bw = new BackgroundWorker();
bw.DoWork += DoWorkFunc;
void DoWorkFunc(object a, EventArgs b)
{
TestMethod("", "", "");
}
Run Code Online (Sandbox Code Playgroud)
参数在(a,b)代码部分中定义.这些对应于object sender和DoWorkEventArgs e.也就是说,您的lambda类似于以下代码:
BackgroundWorker bw = new BackgroundWorker();
bw.DoWork += new DoWorkEventHandler(MyFunction);
void MyFunction(object a, DoWorkEventArgs b)
{
TestMethod("", "", "");
}
Run Code Online (Sandbox Code Playgroud)
您没有使用参数或返回值的事实TestMethod是无关紧要的.
(与lambda等价物相比)Func<int, int>myFunc = c => c + 1
int MyFunction(int c)
{
return c + 1;
}
Run Code Online (Sandbox Code Playgroud)
委托的论点根本就没有用过.Lambda等效于以下方法:
void LambdaMethod(object a, DoWorkEventArgs b)
{
TestMethod("", "", "");
}
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
1310 次 |
| 最近记录: |