Тип условного выражения не может быть определен (Func)
При назначении метода к типу Func
я получаю ошибку компиляции Type of conditional expression cannot be determined because there is no implicit conversion between 'method group' and 'method group'
.
Это происходит только с оператором ? :
. Код:
public class Test
{
public static string One(int value)
{
value += 1;
return value.ToString();
}
public static string Two(int value)
{
value += 2;
return value.ToString();
}
public void Testing(bool which)
{
// This works
Func<int, string> actionWorks;
if (which) actionWorks = One; else actionWorks = Two;
// Compilation error on the part "One : Two"
Func<int, string> action = which ? One : Two;
}
}
Я нашел некоторую информацию о совместной и контравариантности, но я не вижу, как это относится к ситуации выше. Почему это не работает?
Ответы
Ответ 1
Вам нужно явно предоставить подпись хотя бы одной группы методов. Однако после этого компилятор позволит вам объявить action
как неявно типизированное локальное:
var action = which ? (Func<int, string>)One : Two;
Причина этого в том, что возвращаемый тип operator ?:
не выводится на основе того, что вы пытаетесь назначить, но на основе типов двух выражений. Если типы совпадают или существует неявное преобразование между ними, компилятор успешно выводит тип возврата; в противном случае он жалуется, что конверсия отсутствует.
Ответ 2
При прямом назначении функции делегату компилятор преобразует функцию в требуемый тип делегата, если она соответствует сигнатуре.
Однако, когда вы используете оператор?: в отношении компилятора вы не назначаете непосредственно делегату, поэтому он не знает, какой тип использовать для One и Two, и поэтому он думает, что два типа, используемые в операторе?: не совпадают.
Единственное исправление делает явное преобразование:
Func<int, string> action = which ? new Func<int, string>(One) : new Func<int, string>(Two);
Ответ 3
Решение Jon работает
var action = which ? (Func<int, string>)One : Two;
Другой альтернативой является создание нового анонимного делегата. Это семантически отличается, но я думаю, что это тоже может быть полезно.
Func<int, string> action = x => which ? One(x) : Two(x);
Я нахожу этот lil 'более изящным, хотя и не таким коротким.