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

Тип условного выражения не может быть определен (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;
    }
}

Я нашел некоторую информацию о совместной и контравариантности, но я не вижу, как это относится к ситуации выше. Почему это не работает?

4b9b3361

Ответ 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 'более изящным, хотя и не таким коротким.