C# 操作与Func相同<;TResult>;?

C# 操作与Func相同<;TResult>;?,c#,.net,lambda,delegates,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()

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

代码如下:

// 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();
//与委托匹配的函数
公共静态int DoSomething()
{
Console.WriteLine(“我被召唤”);
返回1;
}
//用法
动作动作=()=>DoSomething();
Func Func=()=>DoSomething();
动作();
func();
我对
操作的理解是,它应该匹配不接受任何参数且不返回任何内容的委托

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

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

代码编译和运行正常,两个输出都
我被调用
。我想知道的是为什么
Action-Action=()=>DoSomething()
不是编译时错误吗?

C编译器足够聪明,能够根据上下文判断出
()=>DoSomething()
的含义不同。当您使用它分配一个
Action
变量时,它会生成一个
Action
(而不是
Func
),忽略
DoSomething()
Action Action=()=>DoSomething()的返回结果
相当于
Action Action=()=>{DoSomething();}


Func-Func=()=>DoSomething()
相当于
Func=()=>{return DoSomething();}

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

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

// Compile-time failure
// error CS0407: 'int Test.DoSomething()' has the wrong return type
Action action = DoSomething; 
(对于
Func
可以使用相同的方法进行组转换。)

但实际上,你做的事情更像这样:

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

你的理解都是正确的。可能会引起混淆的是您的具体用法。Func和Action都很好。两个电话都很好。我认为可以说明你的问题的情况是:

var x=动作(5);//不好
变量y=func(5);//好的

您的示例代码只是忽略了返回值,这就是为什么它们看起来是一样的。无异于

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

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

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

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

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

因此,您正在告诉编译器如何根据分配给它的类型解释lambda。

>>但是操作没有-它到底是如何失败的?代码行
Action Action=(x)=>DoSomething(x)操作
需要匹配不返回值的委托?@singsuyash C#编译器足够聪明,能够发现
(x)=>DoSomething(x)
根据上下文意味着不同的事情。当您使用它分配一个
Action
变量时,它会生成一个
Action
,而不是
Func
,并忽略
DoSomething(x)
的返回结果。您可以调用
DoSomething
方法并“忽略”返回值(例如
DoSomething(x)
),并且可以使用返回值(例如,
var retVal=DoSomething(x)
)-两者都可以工作和编译。您的问题是什么?您的代码非常好,可以编译并运行。值得注意的是,方法组转换的错误类似于
预期的带有“void DoSomething(object)”的方法'签名
@DaveZych:Done,以及我收到的实际错误消息。感谢@JonSkeet提供更新的答案:)是的,我以后会小心不要这样更改它。