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

Почему выражение С# лямбда не может состоять из простого оператора if, не нуждаясь в фигурных скобках?

Рассмотрим следующее лямбда-выражение, которое назначается событию.

foo.BarEvent += (s, e) => if (e.Value == true) DoSomething();

Это выглядит довольно прямолинейно и состоит только из одной строки кода. Итак, почему я получаю следующие 2 ошибки от отладчика?

Недопустимый термин выражения 'if'


В качестве оператора

можно использовать только присвоение, вызов, приращение, декремент, ожидание и новые объектные выражения.

Чтобы устранить эту проблему, все, что вам нужно сделать, это обернуть оператор if в скобках.

foo.BarEvent += (s, e) => { if (e.Value == true) DoSomething(); };
//Errors now disappear!

Я понимаю, что говорят эти сообщения об ошибках. То, что я не понимаю, является причиной того, что оператор с одним условием if будет проблемой для компилятора и почему первое назначение лямбда считается сломанным.

Может кто-нибудь объяснить проблему?

4b9b3361

Ответ 1

Без { } вы объявляете тело выражения, а { } - тело оператора. См. Лямбда-выражения (Руководство по программированию на С#):

  • выражение lambda возвращает результат выражения

  • A statement lambda напоминает выражение lambda, за исключением того, что оператор заключен в фигурные скобки [...] Тело оператора lambda может состоять из любого количества операторов.

Итак, если вы хотите выражение, а не выражение, используйте фигурные скобки.

Ответ 2

Смотрите Лямбда-выражения.

Существует два типа лямбда, выражение Lambdas (no {}) и Statement Lambdas (с {}).

Ключевое различие между ними заключается в том, что выражение Lambdas определено для возврата значения, вычисленного по их правой стороне. Но if() - это выражение, а не выражение. Нет значения, связанного с if. Вы заметите, что все "разрешенные" элементы языка в сообщении об ошибке, которые вы предоставляете, являются выражениями: они вычисляют значение.

Ответ 3

Как я понимаю, для реализации этого не было бы проблемой. Команда С# уже реализовала более страшные функции (например, LINQ)

Но проблема в том, где вы рисуете линию?

если

b => if (b) DoSomething()` 

разрешено, то почему бы не

b => if (b) {DoSomething1(); DoSomething2();}

. Или

list => foreach (var item in list) DoSomething(item)

и т.д. и т.д.... И прежде чем вы это узнаете, у вас есть целая команда, поддерживающая практически тривиальную функцию.

Единственный верный способ не иметь ошибок в функции - не реализовать эту функцию.

Текущая реализация является оптимальной, поскольку она работает в большинстве случаев, и она не слишком громоздка для остальных (простая {} не слишком сильно затрудняет чтение, упрощая компилятор).

Ответ 4

Посмотрите на это таким образом. У вас есть условное утверждение, которое срабатывает по одной строке, если оно правильно.

if (stuff) do stuff;

Что также можно записать

if (stuff)
     do stuff;

Поскольку вы вызываете только одну строку кода, вам не нужны два скобки. Если бы это было больше, тогда вам пришлось бы использовать скобки.

if (stuff)
{
     do stuff;
     do more stuff;
}

Затем вы комбинируете его с анонимным методом, который ведет себя аналогичным образом

() => do stuff;

Более одного оператора использует скобки так же, как условные.

() => {do stuff; do more stuff;}

Но теперь вы вложите их, но все еще ожидаете, что сможете использовать короткий отрезок. На самом деле это то, что есть, короткое сокращение, которое подразумевает скобки для одного утверждения.

Итак, вы размещаете один ярлык внутри другого ярлыка. С# просто заставляет вас явно указывать вложенный ярлык.