Оператор?'не может быть применен к операнду типа 'T'

пытаюсь сделать Feature generic, а затем внезапно компилятор сказал

оператора?'не может быть применен к операнду типа '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 one-liner.

3 ответов


так как не все может быть null, вы должны сузить T быть чем-то ничтожным (он же object). Структуры не могут быть null, и перечисления тоже.

добавлять where on class решить проблему:

public abstract class Feature<T> where T : class

так почему же это просто не работает?

Invoke() доходность T. Если GetValue is null на ? оператор устанавливает возвращаемое значение типа T to null, который он не может. Если T is int например, это не может сделать его недействительным (int?) так как фактический тип требуется (T = int) не является.

если вы измените T на int в вашем коде, вы увидите очень четко проблему. Конечный результат того, о чем вы просите, таков:--23-->

get
{
    int? x = GetValue?.Invoke();
    return x.GetValueOrDefault(0);
}

это не то, что оператор нулевого распространения сделает для вас. Если вы вернетесь к использованию default(T) он точно знает, что делать, и вы избегаете "проблемного" нулевого распространения.


T должен быть ссылочным типом или типом nullable

public abstract class Feature<T> where T : class
{
    // ...
}

насколько я знаю ?. оператор жестко закодирован для работы с null, то есть он работает для ссылочных типов или типов значений nullable, но не нормальный типы значений. Проблема, скорее всего, в том, что оператор возвращает null если выражение null вместо default(T).

вы можете исправить это, ограничив T to class здесь.