Оператор '?' не может быть применен к операнду типа 'T'
Пытаясь сделать Feature
универсальный, а потом вдруг компилятор сказал
Оператор '?' не может быть применен к операнду типа 'T'
Вот код
public abstract class Feature<T>
{
public T Value
{
get { return GetValue?.Invoke(); } // here is error
set { SetValue?.Invoke(value); }
}
public Func<T> GetValue { get; set; }
public Action<T> SetValue { get; set; }
}
Вместо этого можно использовать этот код
get
{
if (GetValue != null)
return GetValue();
return default(T);
}
Но мне интересно, как исправить эту симпатичную однострочную версию C# 6.0.
3 ответа
Поскольку не все может быть null
нужно сузить T
быть чем-то обнуляемым (иначе object
). Структуры не могут быть нулевыми и не могут перечислять.
Добавление where
на class
решает проблему:
public abstract class Feature<T> where T : class
Так почему же это не работает?
Invoke()
доходность T
, Если GetValue
является null
, ?
Оператор устанавливает возвращаемое значение типа T
в null
что не может. Если T
является int
например, это не может сделать это обнуляемым (int?
) так как фактический тип требуется (T
знак равно int
) нет
Если вы измените T
быть int
в вашем коде вы увидите проблему очень четко. Конечный результат того, что вы спрашиваете, таков:
get
{
int? x = GetValue?.Invoke();
return x.GetValueOrDefault(0);
}
Это не то, что оператор с нулевым распространением сделает для вас. Если вы вернетесь к использованию default(T)
он точно знает, что делать, и вы избегаете "проблемного" нуль-распространения.
T
должен быть ссылочным типом или обнуляемым типом
public abstract class Feature<T> where T : class
{
// ...
}
Насколько я знаю ?.
оператор жестко запрограммирован для работы с null
то есть он работает для ссылочных типов или типов значений, допускающих значение NULL, но не для нормальных типов значений. Проблема, вероятно, что оператор возвращает null
если выражение было null
вместо default(T)
,
Вы можете исправить это, ограничив T
в class
Вот.