Анонимная функция, преобразованная в пустой возвращающий делегат, не может вернуть значение - PullRequest
3 голосов
/ 22 марта 2019

У меня есть общий вопрос: в приведенном ниже коде C # поток tFour не может быть создан, и компилятор показывает мне следующую ошибку: " Анонимная функция, преобразованная в возвращаемый делегат void, не может вернуть значение «

КОД

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 создаются без ошибок. Так почему же лямбда-выражение позволяет передавать делегат метода с возвращаемым (не пустым) значением и несколькими параметрами (ThrowNum(2), newF()), в то время как анонимный метод с возвращаемым значением (delegate () { int x = ThrowNum(2); return x;}), определенным с помощью ключевого слова делегата, не может быть передан? Я думал, что в обоих случаях мы имеем дело с анонимными методами? Я знаю, что Thread принимает только два типа подписей: void DoSomething() и void DoSomething(object o), но в чем заключается основное различие между инициализацией tTwo и tFour с использованием одного (?) Анонимного метода? Некоторое время я пытался найти ответ, но безуспешно. Спасибо

1 Ответ

4 голосов
/ 22 марта 2019

То, что лямбда-выражение в выражении содержит результат, не означает, что оно используется. Это хорошо для лямбда-выражения, которое возвращает результат для преобразования в делегат с типом возврата 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 .

Соответствующая часть стандарта ECMA C # 5 - 11.7.1:

В частности, анонимная функция F совместима с типом делегата D при условии:

  • ...
  • Если тело F является выражением, и либо D имеет тип возврата void, либо F асинхронно, а D имеет возврат Задача типа, тогда, когда каждому параметру F присваивается тип соответствующего параметра в D, Тело F является допустимым выражением (w.r.t §12), которое будет разрешено как выражение-выражение (§13.7).
...