54

我有以下通用方法,但是 VS 给了我一个编译错误。(运算符 '??' 不能应用于类型为 'T' 和 'T' 的操作数)

public static T Method<T>(T model) where T : new()
{
    var m = model ?? new T();
}

有人知道为什么吗?

编辑:在我的情况下,可能是因为 T 可以是结构,而结构是不可为空的类型?

4

8 回答 8

86

??是空合并运算符。它不能应用于不可为空的类型。由于T可以是任何东西,它可以是一个int或其他原始的、不可为空的类型。

如果您添加条件where T : class(必须在之前指定new()),它会强制T成为一个可以为空的类实例。

于 2013-06-13T06:21:29.833 回答
58

您应该添加class约束:

public static T Method<T>(T model) where T : class, new()
{
    var m = model ?? new T();

    return m;
}

你也应该回来m

注意:正如@KristofDegrave 在他的评论中提到的那样,我们必须添加class约束的原因是因为 T 可以是值类型,就像int并且由于??运算符(null-coalescing)检查可以为空的类型,所以我们必须添加class约束排除值类型。

编辑:Alvin Wong 的回答也涵盖了可空类型的情况;哪些实际上是结构,但可以是 ?? 的操作数 操作员。请注意,对于可空类型,如果没有 Alvin 的重载版本,Method它将返回。null

于 2013-06-13T06:22:17.937 回答
32

许多人已经指出,class为泛型添加约束将解决问题。

如果您希望您的方法也适用Nullable<T>,您可以为其添加重载:

// For reference types
public static T Method<T>(T model) where T : class, new()
{
    return model ?? new T();
}

// For Nullable<T>
public static T Method<T>(T? model) where T : struct
{
    return model ?? new T(); // OR
    return model ?? default(T);
}
于 2013-06-13T09:14:05.197 回答
8

您需要指定您的T类型是一个对泛型类型有约束的类:

public static T Method<T>(T model) where T : class, new()
{
    return model ?? new T();
}
于 2013-06-13T06:19:43.943 回答
4

由于 T 可以是任何类型,因此不能保证 T 会有一个静态的 ?? 运算符或类型 T 可以为空。

?? 运算符(C# 参考)

这 ??运算符称为 null-coalescing 运算符,用于为可空值类型或引用类型定义默认值。

于 2013-06-13T06:20:10.103 回答
4

由于某种原因,该??运算符不能用于不可为空的类型,即使它应该等同于model == null ? new T() : model,并且您可以与不可为空的类型进行空比较。

通过使用三元运算符或 if 语句,您可以在没有任何额外约束的情况下准确地获得您正在寻找的内容:

public static T Method<T>(T model) where T : new()
{
   var m = model == null ? new T() : model;
}
于 2013-06-13T06:39:06.270 回答
0

model ?? new T()意味着model == null ? new T() : model。不保证模型不可为空且==不可申请null且不可为空的对象。将约束更改为where T : class, new()应该有效。

于 2013-06-13T06:21:55.333 回答
0

将 T 标记为“类”,您就可以开始了。

于 2013-06-13T06:21:57.873 回答