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

Назначение лямбда-выражения с использованием условного (тройного) оператора

Я пытаюсь использовать условный (тройной) оператор для назначения правильного лямбда-выражения переменной, в зависимости от условия, но я получаю ошибку компилятора: Тип условного выражения не может быть определен, потому что нет никакого неявного преобразования между "лямбда-выражение" и "лямбда-выражение". Я могу использовать регулярное if-else для решения этой проблемы, но условный оператор имеет больше смысла для меня (в этом контексте), сделает код более кратким, по крайней мере, мне хотелось бы узнать причины, почему это не так, т работы.

// this code compiles, but is ugly! :)
Action<int> hh;
if (1 == 2) hh = (int n) => Console.WriteLine("nope {0}", n);
else hh = (int n) => Console.WriteLine("nun {0}", n);

// this does not compile
Action<int> ff = (1 == 2)
  ? (int n) => Console.WriteLine("nope {0}", n)
  : (int n) => Console.WriteLine("nun {0}", n);
4b9b3361

Ответ 1

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

Action<int> ff = (1 == 2)
  ? (Action<int>)((int n) => Console.WriteLine("nope {0}", n))
  : (Action<int>)((int n) => Console.WriteLine("nun {0}", n));

Ответ 2

Это будет работать.

Action<int> ff = (1 == 2)
? (Action<int>)((int n) => Console.WriteLine("nope {0}", n))
: (Action<int>)((int n) => Console.WriteLine("nun {0}", n)); 

Здесь есть две проблемы:

  • Выражение
  • Тернарный оператор

1. Проблема с выражением

Компилятор сообщает вам точно, что неправильно - 'Type of conditional expression cannot be determined because there is no implicit conversion between 'lambda expression' and 'lambda expression'.

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

Выражение лямбда не имеет определенного типа - оно просто конвертируется в дерево выражений.

Выражение доступа к членству (которое вы пытаетесь сделать) доступно только в формах

primary-expression . identifier type-argument-list(opt)
predefined-type . identifier type-argument-list(opt)
qualified-alias-member . identifier type-argument-list(opt)

... и выражение лямбда не является первичным выражением.

2. Проблема с тройным оператором

Если мы делаем

bool? br = (1 == 2) ? true: null;

Это приводит к ошибке, точно такой же, как ваша. 'Type of conditional expression cannot be determined because there is no implicit conversion between 'bool' and '<null>'

Но ошибка исчезнет, ​​если мы сделаем это

bool? br = (1 == 2) ? (bool?)true: (bool?)null;

Литье одной стороны также будет работать

bool? br = (1 == 2) ? (bool?)true: null;

ИЛИ

bool? br = (1 == 2) ? true: (bool?)null;

Для вашего случая

Action<int> ff = (1 == 2)
? (Action<int>)((int n) => Console.WriteLine("nope {0}", n))
: ((int n) => Console.WriteLine("nun {0}", n)); 

ИЛИ

Action<int> ff = (1 == 2)
? ((int n) => Console.WriteLine("nope {0}", n))
: (Action<int>)((int n) => Console.WriteLine("nun {0}", n)); 

Ответ 3

Фактически, с типом вывода вы можете:

  • Используйте переменную var для локальной переменной
  • Только первое выражение тернарного оператора
  • Опустить тип параметра лямбда, поскольку он может быть выведен

Результат намного более краткий. (Я позволяю вам решить, является ли это более читаемым.)

    var ff = condition 
             ? (Action<int>)(n => Console.WriteLine("nope {0}", n)) 
             : n => Console.WriteLine("nun {0}", n);

Ответ 4

В основном такой же ответ, как и другие, в другой форме

Action<int> ff = (1 == 2) 
? new Action<int>(n => Console.WriteLine("nope {0}", n)) 
: new Action<int>(n => Console.WriteLine("nun {0}", n));