操作员 '?'不能应用于 'T' 类型的操作数

Operator '?' cannot be applied to operand of type 'T'

试图使 Feature 通用,然后编译器突然说

Operator '?' cannot be applied to operand of type '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 单行代码。

据我所知,?. 运算符被硬编码为与 null 一起使用,也就是说,它适用于引用类型或可空值类型,但不适用于 normal 值类型。问题可能是运算符 returns null 如果表达式是 null 而不是 default(T).

您可以通过在此处将 T 限制为 class 来修复它。

T 必须是引用类型或可空类型

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

由于并非所有内容都可以 null,因此您必须将 T 缩小为可以为 null 的内容(又名 object)。结构不能为空,枚举也不能。

class 上添加 where 确实解决了问题:

public abstract class Feature<T> where T : class

那为什么它不起作用?

Invoke() 产生 T。如果 GetValuenull,则 ? 运算符会将类型 T 的 return 值设置为 null,但它不能这样做。例如,如果 Tint,它不能使它可以为空 (int?),因为所需的实际类型 (T = int) 不是.

如果你在代码中把T改成int,你会很清楚地看到问题所在。你问的最终结果是这样的:

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

这不是零传播运算符会为您做的事情。如果你恢复使用 default(T) 它确实知道该做什么并且你避免了 'problematic' 空传播。