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

Почему "Func <bool> test = value? F: F" не компилируется?

Я видел похожие вопросы к этому, но они связаны с разными типами, поэтому я думаю, что это новый вопрос.

Рассмотрим следующий код:

public void Test(bool value)
{
    // The following line provokes a compiler error:
    // "Type of conditional expression cannot be determined because there is 
    // no implicit conversion between 'method group' and 'method group".

    Func<bool> test = value ? F : F;
}

public bool F()
{
    return false;
}

Теперь, согласно стандарту С# 3.0,

Второй и третий операнды?: оператор управляет типом условное выражение. Пусть X и Y - типы второго и третьего операнды. Тогда,

Если X и Y одного типа, то это тип условного В противном случае, если неявное преобразование (§6.1) существует от X до Y, но не от Y до X, то Y - тип условное выражение. В противном случае, если подразумевается неявное преобразование (§6.1) от Y до X, но не от X до Y, тогда X - тип условного выражение. В противном случае выражение тип может быть определен, и ошибка времени компиляции.

Мне кажется, что в моем примере кода X и Y должны быть одного типа, так как они являются одним и тем же объектом Func. Почему он не компилируется?

4b9b3361

Ответ 1

Вопрос значительно изменился, поэтому мой оригинальный ответ немного ушел.

Однако проблема, по сути, одна и та же. То есть может быть любое количество сопоставлений делегатов для F, и поскольку не существует неявного преобразования между двумя идентичными объявлениями делегатов, тип F не может быть преобразован в Func<bool>.

Аналогично, если вы объявляете

private delegate void X();
private delegate void Y();
private static void Foo() {}

Вы не можете сделать

X x = Foo;
Y y = x;

Оригинальный ответ:

Это не работает, потому что группы методов нельзя назначить неявно типизированной переменной.

var test = Func; тоже не работает.

Причина в том, что для Func может быть любое количество типов делегатов. Например. Func соответствует обеим этим объявлениям (в дополнение к Action)

private delegate void X();
private delegate void Y();

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


См. archil answer для конкретного примера одного из способов исправить это. То есть он показывает, как будет выглядеть исправленный код [при условии, что делегат, которого вы хотите сопоставить, Action].

Ответ 2

var test = value ? (Action)Func: (Action)Func;

Собственно, type метода выражается делегатом, который соответствует ему. System.Action, который я использовал для приведения методов к, является делегатом с сигнатурой, возвращающей void и не принимающей никаких параметров, - это соответствует вашему методу Func(). И теперь ваш test будет знать, что это тип System.Action. Делегаты - это что-то вроде интерфейсов для методов. Взгляните на http://msdn.microsoft.com/en-us/library/ms173171(v=vs.80).aspx

Ответ 3

Поскольку

public bool F()

Является Action<bool> (т.е. ничего не принимает и возвращает bool)

В то время как Func<bool> подразумевает

public void F(bool something)

Скорее всего...