与Func <tresult>相同的动作?

时间:2015-10-22 14:33:49

标签: c# .net lambda delegates

我遇到了一些我需要一些知识的情况。

以下是代码:

// A function to match the delegate
public static int DoSomething()
{
   Console.WriteLine("i am called");
   return 1;
}

// Usage
Action action = () => DoSomething();
Func<int> func = () => DoSomething();
action();
func();

我对Action的理解曾经是它应该匹配一个不接受任何参数并且什么都不返回的委托。

对于Func<int>,它应匹配不接受参数的委托,并返回int

DoSomething方法返回一个整数,因此我的问题是:() => DoSomething()是一个返回int的委托。 Func按预期工作,但Action没有。为什么?我在这里没有理解什么?

代码编译并正常运行,两者都输出i am called。我想知道的是为什么Action action = () => DoSomething();不是编译时错误?

5 个答案:

答案 0 :(得分:10)

  

我想知道的是为什么Action action = () => DoSomething();不是编译时错误?

它编译因为你有一个lambda表达式调用该方法但忽略了结果。您无法使用方法组转换,例如

// Compile-time failure
// error CS0407: 'int Test.DoSomething()' has the wrong return type
Action action = DoSomething; 

Func<Action, int>的方法组转换方法相同。)

但相反,你正在做更多这样的事情:

Action action = DoSomethingAndIgnoreResult;
...
private static void DoSomethingAndIgnoreResult()
{
    DoSomething(); // Hey, I'm ignoring the result. That's fine...
}

答案 1 :(得分:8)

Action action = () => DoSomething();相当于
Action action = () => { DoSomething(); };

Func<int> func = () => DoSomething();相当于
Func<int> func = () => { return DoSomething(); };

答案 2 :(得分:3)

C#编译器非常聪明,可以根据上下文确定() => DoSomething()意味着不同的东西。当您使用它来分配Action变量时,它会生成Action(而不是Func<int>),忽略DoSomething()的返回结果。

答案 3 :(得分:1)

  

DoSomething方法返回一个整数,因此我的问题是:(x) => DoSomething(x)是一个接受object并返回int的委托。 Func按预期工作,但Action没有。为什么?我在这里没有理解什么?

您理解中的缺陷就在这里:(x) => DoSomething(x)没有类型。这不是什么。编译器需要上下文来确定它的类型。 lambda本身并不是特别的,这就是为什么你不能将var与lambda表达式一起使用的原因:编译器不知道lambda应该是什么类型,所以它无法推断出类型。

例如,(x) => DoSomething(x)也可以是表达式树:

Expression<Func<object, int>> e = (x) => DoSomething(x)

所以你要告诉编译器如何根据你指定的类型来解释lambda。

答案 4 :(得分:0)

您的所有理解都是正确的。这是您的具体用法,可能会导致混淆。 Func和Action都很好。两个电话都很好。我认为可以说明你的问题的案例是:

var x = action(5); // NOT ok var y = func(5); // ok

您的示例代码只是忽略了返回值,这就是为什么它们似乎是相同的。与

无异

void Foo1(int x) { return; } void Foo2(int x) { return 1; } Foo1(5); Foo2(5);