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

Sin*_*atr 23 c# generics delegates c#-6.0 null-propagation-operator

试图制作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; }
}
Run Code Online (Sandbox Code Playgroud)

可以使用此代码

get
{
    if (GetValue != null)
        return GetValue();
    return default(T);
}
Run Code Online (Sandbox Code Playgroud)

但我想知道如何修复那个漂亮的C#6.0单线程.

Pat*_*man 32

既然不是一切都可以null,你必须缩小T到可以为空的东西(又名a object).结构不能为空,也不能枚举.

添加whereon class确实解决了问题:

public abstract class Feature<T> where T : class
Run Code Online (Sandbox Code Playgroud)

那为什么它不起作用呢?

Invoke()收益率T.如果GetValuenull,则?运算符将类型的返回值设置Tnull,但不能.如果Tint,例如,它不能使它可为空的(int?),因为所需要的实际类型(T= int)不是.

如果您更改Tint代码,您将非常清楚地看到问题.你问的最终结果如下:

get
{
    int? x = GetValue?.Invoke();
    return x.GetValueOrDefault(0);
}
Run Code Online (Sandbox Code Playgroud)

这不是零传播运算符将为您做的事情.如果你恢复使用default(T)它确实知道该做什么,你就避免了"有问题"的零传播.

  • 我只是接受C#编译器不允许这样做,你需要你的选项#2才能使这个工作.不是所有东西都必须是一个班轮,对吧? (4认同)
  • @Sinatr你可以用另一种方式来做,把T引用到struct:`public abstract class Feature <T>其中T:struct`.然后将所有`T`类型标记为null.`public Func <T?>`,`public Action <T?>`,`public T?值.但是,通过这种方式,您只能使用值类型. (2认同)
  • @kjbartel`Invoke()`产生`T`.如果`GetValue`是`null`,`?`运算符将`T`的返回值设置为`null`,它不能. (2认同)

Gyö*_*zeg 8

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

public abstract class Feature<T> where T : class
{
    // ...
}
Run Code Online (Sandbox Code Playgroud)