new Action()和lambda有什么区别?

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)

  • "如果用var声明它,C#编译器怎么能计算出什么类型的动作?" 简单:函数类型应该是第一类结构类型,而不是这个命名委托的东西.引用的代码应该注明.但我想现在不会改变:). (4认同)
  • VB.Net能够通过根据用途动态生成委托类型来解决这个问题.因为VB已经区分了void和非void返回函数(子函数和函数),所以它使区分更容易 (3认同)

Jar*_*Par 9

你确认第二行实际编译了吗?它不应该编译,因为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