Geo*_*uer 40 c# lambda delegates .net-3.5
所以当我写这样的东西
Action action = new Action(()=>_myMessage = "hello");
Run Code Online (Sandbox Code Playgroud)
重构专业!强调这是一个冗余的代表创建,并允许我缩短它
Action action = () => _myMessage="hello";
Run Code Online (Sandbox Code Playgroud)
这通常很有效. 通常,但并非总是如此.例如,Rhino Mocks有一个名为Do的扩展方法:
IMethodOptions<T> Do(Delegate action);
Run Code Online (Sandbox Code Playgroud)
传递第一个版本,但第二个版本没有.究竟是什么在这里?
Jon*_*eet 60
第一个版本实际上是这样做的:
Action tmp = () => _myMessage = "hello";
var action = new Action(tmp);
Run Code Online (Sandbox Code Playgroud)
您遇到的问题是编译器必须知道应该将lambda表达式转换为什么类型的委托(或表达式树).这就是为什么这个:
var action = () => _myMessage="hello";
Run Code Online (Sandbox Code Playgroud)
实际上不编译 - 它可以是任何没有参数的委托类型,也没有返回值或相同的返回类型_myMessage
(可能是这样string
).例如,所有这些都是有效的:
Action action = () => _myMessage="hello";
Func<string> action = () => _myMessage="hello";
MethodInvoker action = () => _myMessage="hello";
Expression<Action> = () => _myMessage="hello";
// etc
Run Code Online (Sandbox Code Playgroud)
C#编译器怎么会制定出什么类型action
的意思是,如果它是与声明var
?
调用方法(对于你的Rhino Mocks示例)时最简单的方法是转换:
methodOptions.Do((Action) (() => _myMessage = "hello"));
Run Code Online (Sandbox Code Playgroud)
你确认第二行实际编译了吗?它不应该编译,因为C#不支持将lambda表达式赋值给隐式类型变量(CS0815).这行可以在VB.Net中使用,因为它支持匿名委托创建(从VB 9.0开始).
由于第二行不应编译的原因相同,Rhino Mocks版本无法编译.C#不会自动推断lambda表达式的类型.Lambda表达式必须在可以确定它们要实现的委托类型的上下文中使用.第一行很有用,因为预期的类型很明确:Action.Rhino Mocks版本不起作用,因为Delegate更类似于抽象委托类型.它必须是具体的委托类型,例如Action或Func.
有关该主题的详细讨论,您应该阅读Eric Lippert关于该主题的博客文章:http://blogs.msdn.com/ericlippert/archive/2007/01/11/lambda-expressions-vs-anonymous-methods-part -two.aspx