Ответ 1
Lambdas в С# не имеет типов, пока они не будут использоваться в контексте, который передает их в делегат или тип выражения. Вот почему вы не можете сказать
var x = () => "some lambda";
Вам может понравиться
Надеюсь, я правильно назвал название своего вопроса.
В С# я могу использовать lambdas (как делегаты) или старший синтаксис делегата для этого:
Func<string> fnHello = () => "hello";
Console.WriteLine(fnHello());
Func<string> fnHello2 = delegate()
{
return "hello 2";
};
Console.WriteLine(fnHello2());
Итак, почему я не могу "встроить" лямбда или тело делегата и не улавливать его в именованной переменной (делая ее анонимной)?
// Inline anonymous lambda not allowed
Console.WriteLine(
(() => "hello inline lambda")()
);
// Inline anonymous delegate not allowed
Console.WriteLine(
(delegate() { return "hello inline delegate"; })()
);
Пример, который работает в javascript (только для сравнения):
alert(
(function(){ return "hello inline anonymous function from javascript"; })()
);
Создает ожидаемое окно предупреждения.
UPDATE: Кажется, у вас может быть встроенная анонимная лямбда в С#, если вы настроили ее соответствующим образом, но количество() начинает расстраиваться.
// Inline anonymous lambda with appropriate cast IS allowed
Console.WriteLine(
((Func<string>)(() => "hello inline anonymous lambda"))()
);
Возможно, компилятор не может вывести sig анонимного делегата, чтобы узнать, какой Console.WriteLine() вы пытаетесь вызвать? Кто-нибудь знает, почему требуется конкретный отбор?
Lambdas в С# не имеет типов, пока они не будут использоваться в контексте, который передает их в делегат или тип выражения. Вот почему вы не можете сказать
var x = () => "some lambda";
Вам может понравиться
Кажется, что это сработает, если вы дадите ему тип cast:
String s = ((Func<String>) (() => "hello inline lambda"))();
Неужели это бесполезно? Не совсем. Возьмите ниже:
String s;
{
Object o = MightBeNull();
s = o == null ? "Default value" : o.ToString();
}
Теперь рассмотрим следующее:
String S = ((Func<Object,String>)(o => o == null ? "Default value" : o.ToString())
)(MightBeNull());
Это немного уродливо, но оно компактно.
Когда вы пишете Func<string> = ...
, компилятор знает, что он должен создать объект типа Func<string>
. Но когда вы пишете этот делегат inline, компилятор не знает объект, тип которого он должен создать.
Сказав вышеизложенное, можно сделать очевидный вывод: просто скажите компилятору тип явно!
Console.WriteLine( new Func<string>( () => "Hello" )() );
UPDATE
Хорошо, когда я писал ответ, вы обновили свой пост. Я считаю, что мой ответ выше уже отвечает на вопрос "зачем нужен этот конкретный тип". Повторить: поскольку компилятор не знает объект, тип которого создается.
Теперь немного уточнить, что "компилятор не может вывести часть анонимного делегата". Понимаете, это не похоже на JavaScript. В С# нет общего типа "функция" (или "метод" ). Каждый делегат должен иметь явно заданное имя подписи и типа. И когда вы создаете делегат, компилятор должен знать, какой тип.
Теперь я вижу, как вы можете подразумевать, что компилятор может просто построить тип делегата "на лету", как это происходит с анонимными типами объектов (aka new { a = 1, b = "xyz" }
). Но подумайте об этом на мгновение: в любом случае, для такого делегата, вероятно, не будет пользы. Я имею в виду, вы не можете передать его другому методу, потому что этот метод должен сначала объявить типы его аргументов. И вы можете сделать из него событие, потому что, опять же, у вас должен быть именованный тип.
Что-то вроде этого...
Вы можете использовать встроенные лямбда-выражения для методов, которые принимают параметр Delegate.
Однако есть небольшой catch - если параметр вводится в качестве базового типа Delegate, вам нужно явно указать его на определенный вывод делегата (например, Action); иначе компилятор будет жаловаться.
Похожие вопросы:
Анонимный метод в вызове Invoke
Анонимные методы и делегаты