Подтвердить что ты не робот

Какой фактический тип лямбды в С#?

Я читал, что С# lambdas может быть неявно преобразован в Action или Func, но lambda нельзя выполнить напрямую Определить функцию лямбда и немедленно ее выполнить Например:

int n = (()=>5)(); //doesn't work
int n = ((Func<int>)(()=>5))(); //works

Итак, каков фактический тип лямбды и почему он не может быть непосредственно вызван? Это потому, что система типа С# "слабее", чем Haskell или Scala одна?

4b9b3361

Ответ 1

Лямбда-выражение не имеет типа. Он не может, поскольку любой тип в мире .NET, который он мог бы иметь, также жестко кодирует тип параметров лямбда и результат. Теперь рассмотрим:

x => x + 1

Какой тип может иметь x? Каким будет результат? Не существует единого ответа, и выражение лямбда действительно может быть преобразовано в Func<int, int>, Func<double, double> и многие другие типы делегатов с разными параметрами. Придавая выражению лямбда, тип будет запрещать такие выражения. С# действительно хотел разрешить такие выражения, поэтому был разработан так, чтобы не приводить к таким выражениям никакого типа.

Ответ 2

Это связано с тем, что () => 5 может быть совместим с различными типами делегатов (например, у вас может быть пользовательский delegate, который ничего не принимает и возвращает int). А для создания delegate компилятор должен знать точный тип. Он не может просто выбрать случайный тип, который соответствует вашим потребностям. Поэтому, если вы не примените его к фактическому типу делегата, вы не можете Invoke его.

В случаях, когда метод ожидает a delegate, это преобразование неявно выполняется компилятором:

void Foo(Func<int> func) {  }

Foo(() => 5); 

И также важно знать, что delegates фактически являются классами за кулисами. И каждый раз, когда вы создаете экземпляр delegate, компилятор создает экземпляр этого class. Поэтому в любом случае вам нужно указать тип, чтобы компилятор знал, какой тип использовать.