我有一个普遍的问题:在线程tFour
下的C#代码中无法创建,编译器向我显示以下错误:“ 将匿名函数转换为void返回的委托无法返回值< / em>”
代码
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
namespace DelegatesAndLambda
{
class Program
{
public static int ThrowNum(object a)
{
Console.WriteLine(a);
return 2 * (int)a;
}
static void Main(string[] args)
{
Func<int> newF = delegate () { int x = ThrowNum(2); return x; };
Thread tOne = new Thread( delegate () { int x = ThrowNum(2); });
Thread tTwo= new Thread(()=> ThrowNum(2));
Thread tThree = new Thread(() => newF());
Thread tFour = new Thread(delegate () { int x = ThrowNum(2); return x;});
}
}
}
但是,线程tOne
,tTwo
和tThree
的创建没有错误。那么,为什么lambda表达式允许传递带有返回(非无效)值和多个参数(ThrowNum(2), newF()
)的方法委托,而使用委托关键字定义的具有返回值(delegate () { int x = ThrowNum(2); return x;}
)的匿名方法可以传递不通过?我以为在两种情况下我们都处理匿名方法?我确实知道Thread
仅接受两种类型的签名:void DoSomething()
和void DoSomething(object o)
,但是tTwo
和tFour
的初始化使用的主要区别是什么?同样(?)匿名方法?我一直在寻找答案,但没有成功。
谢谢
答案 0 :(得分:3)
仅因为表达式健全的lambda表达式具有结果并不意味着已使用它。只要lambda表达式的主体是有效的 statement表达式,它就可以将返回结果的lambda表达式转换为具有void
返回类型的委托。这是一个简单的示例:
using System;
class Test
{
static int Method() => 5;
static void Main()
{
Action action = () => Method();
}
}
那很好,因为Method()
是有效的语句表达式。它只是调用方法,而忽略结果。这将无效有效,因为1 + 1
不是有效的语句表达式:
// error CS0201: Only assignment, call, increment, decrement,
// await, and new object expressions can be used as a statement
Action action = () => 1 + 2;
没有像表达式一样的匿名方法,所以事情变得简单了一些:您无法从匿名方法返回值,而是使用void
将匿名方法转换为委托类型。返回类型。
C#5 ECMA标准的相关部分是11.7.1:
具体来说,匿名函数F与提供的委托类型D兼容:
- ...
- 如果F的主体为表达式,并且D的返回类型为void或F为异步且D的返回 类型Task,然后在为F的每个参数指定D中相应参数的类型时, F的主体是有效的表达式(w.r.t§12),可以用作语句表达式(第13.7节)。