Почему "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. Почему он не компилируется?
Ответы
Ответ 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)
Скорее всего...