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

Могу ли я игнорировать параметры делегата с синтаксисом лямбда?

Мне любопытно, почему С# позволяет мне игнорировать параметры делегата в некоторых случаях, но не другие.

Например, это разрешено:

Action<int> action = delegate { Console.WriteLine("delegate"); };

но это не так:

Action<int> action = () => Console.WriteLine("lambda");

Есть ли способ инициализировать делегат и игнорировать параметры с помощью лямбда? Я знаю, что я могу добавить один параметр в лямбда и исправить предыдущую строку, но это скорее академический вопрос, относящийся к компилятору, и почему и как это работает.

4b9b3361

Ответ 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");