转换为无效返回委托的匿名函数无法返回值

时间:2019-03-22 09:46:34

标签: c# lambda delegates anonymous-function

我有一个普遍的问题:在线程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;});
        }
    }
}

但是,线程tOnetTwotThree的创建没有错误。那么,为什么lambda表达式允许传递带有返回(非无效)值和多个参数(ThrowNum(2), newF())的方法委托,而使用委托关键字定义的具有返回值(delegate () { int x = ThrowNum(2); return x;})的匿名方法可以传递不通过?我以为在两种情况下我们都处理匿名方法?我确实知道Thread仅接受两种类型的签名:void DoSomething()和void DoSomething(object o),但是tTwotFour的初始化使用的主要区别是什么?同样(?)匿名方法?我一直在寻找答案,但没有成功。 谢谢

1 个答案:

答案 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节)。
  •