Могу ли я игнорировать параметры делегата с синтаксисом лямбда?
Мне любопытно, почему С# позволяет мне игнорировать параметры делегата в некоторых случаях, но не другие.
Например, это разрешено:
Action<int> action = delegate { Console.WriteLine("delegate"); };
но это не так:
Action<int> action = () => Console.WriteLine("lambda");
Есть ли способ инициализировать делегат и игнорировать параметры с помощью лямбда? Я знаю, что я могу добавить один параметр в лямбда и исправить предыдущую строку, но это скорее академический вопрос, относящийся к компилятору, и почему и как это работает.
Ответы
Ответ 1
Я считаю, что ваш первый образец фактически создает анонимную функцию, которая может принимать множество разных подписей, тело которых является единственным выражением Console.WriteLine...
. Поскольку он может соответствовать различным сигнатурам, это не вызывает проблемы. Во втором примере сам синтаксис лямбда определяет функцию, которая не принимает параметров с одним и тем же телом. Очевидно, что последнее не соответствует определенному действию, поэтому вы получаете ошибку.
С# Анонимный метод Ссылка
Существует один случай, когда анонимный метод функциональность не найдена в лямбда выражения. Анонимные методы позволяют вы должны опустить список параметров и это означает, что анонимный метод могут быть преобразованы в делегатов с помощью множество подписей. Это не возможно с лямбда-выражениями.
Ответ 2
Продумать ответ tvanfosson; это поведение описано в спецификации языка С# 3.0 (§7.14):
Поведение лямбда-выражений и Анонимные методы-выражения - это то же самое, за исключением следующих пунктов:
• Разрешения анонимного метода позволяют список параметров, который должен быть опущен полностью, уступая конвертируемости делегировать типы любого списка значений Параметры.
• lambda-expressions разрешить параметр типы, которые следует опустить и вывести тогда как выражения анонимного метода требуют, чтобы типы параметров были явно указано.
• Тело лямбда-выражения может быть выражением или блоком оператора тогда как тело выражение anonymous-method должно быть блок оператора.
• Поскольку только лямбда-выражения могут имеют тело выражения, нет выражение anonymous-method может быть успешно преобразован в тип дерева выражений (§4.6).
Я думаю:
Action<int> action = () => Console.WriteLine("lambda");
является эквивалентом:
Action<int> action = delegate() { Console.WriteLine("delegate"); };
который тоже не будет скомпилирован. Как говорит Даниэль Плауист(), явно указано, что нет никаких параметров.
Если существует эквивалент делегата {}, он может быть:
Action<int> action = => Console.WriteLine("lambda")
Что не очень красиво, и я подозреваю, что он подозревается не в духе лямбда-выражений.
Ответ 3
Как говорили другие, нет, вы не можете пропустить объявление параметров лямбда. Но, для чистоты, я предлагаю дать им такое имя, как _. Например
foo.Click += (_,__) => { ... }
Вы не игнорируете их по-своему, но вы указываете, что вам все равно, что они есть, и не будут их использовать.
Ответ 4
Синтаксис() = > ... явно указывает, что лямбда не принимает никаких параметров. Возможно, язык может быть изменен так, чтобы() = > действительно означало "Внесите параметры этой лямбды для меня" так же, как это делает синтаксис делегата, но это сделает язык более сложным. При разработке новых языковых функций вы начинаете с минус 100, и я не думаю, что это проходит тест.
Также могут быть более технические причины, по которым это было бы сложно реализовать (что, вероятно, больше соответствует тому, о чем вы просили, но я сомневаюсь, что технические причины приняли это решение, если оно когда-либо появлялось).
Ответ 5
Я бы сказал, что это принудительное использование параметров лямбда-выражения.
Возьмите первый пример, как бы вы взаимодействовали с переданным значением, там не было локального представления.
Ответ 6
Как насчет этого?
Func<int> lamdapointer = () => TwoArgMethodThatReturnsInt(10,20); // the same method cannot be called with the delegate "NoArgmethodThatReturnsInt"
lamdapointer();
Delegate int NoArgmethodThatReturnsInt();
NoArgmethodThatReturnsInt del = NoArgmethodThatReturnsInt; // only this is possible with delegates
public int TwoArgMethodThatReturnsInt(int x,int y)
{
return x + y;
}
public int NoArgmethodThatReturnsInt()
{
return 20;
}
Ответ 7
Фактически, делегат {} не задает никаких параметров и не подходит для любой подписи метода делегата, поэтому он разрешен в вашем первом проекте.
Лямбда-выражение() = > ...; в частности, указывается параметрический делегат, что противоречит сигнатуре, требуемой Action - делегат с единственным параметром.
Возможно, вы захотите использовать один из следующих вариантов.
Если вам нужно, чтобы действие имело параметр, вы можете сделать это следующим образом ( "_" является юридическим символом для имени идентификатора).
Action<int> action = _ => Console.WriteLine("lambda");
Или вы можете использовать безпараметрическое действие следующим образом:
Action action = () => Console.WriteLine("lambda");