【问题标题】:Operator '??' cannot be applied to operands of type 'T' and 'T'操作员 '??'不能应用于“T”和“T”类型的操作数
【发布时间】:2013-06-09 10:41:03
【问题描述】:

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

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

有人知道为什么吗?

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

【问题讨论】:

    标签: c# generics compiler-errors


    【解决方案1】:

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

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

    【讨论】:

      【解决方案2】:

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

      ?? Operator (C# Reference)

      ??运算符称为空合并运算符,用于 为 可为空的值类型或引用定义默认值 类型

      【讨论】:

        【解决方案3】:

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

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

        【讨论】:

        • new() 条件不强制 T 为可空类型吗?
        • @KristofDegrave no new() 只表示会有一个空的构造器
        • 有没有可能是因为在我的情况下 T 可以是一个结构体,而一个结构体是一个不可为空的类型?
        【解决方案4】:

        model ?? new T() 表示model == null ? new T() : model。不保证模型不可为空,== 不能应用于 null 和不可为空的对象。将约束更改为 where T : class, new() 应该可以工作。

        【讨论】:

          【解决方案5】:

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

          【讨论】:

            【解决方案6】:

            你应该添加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)检查可以为 null 的类型,所以我们必须添加 class 约束来排除值类型。

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

            【讨论】:

            • 当然它们是一样的!但是在问题中使用了第一个。就是刚才提到的。
            • 有没有可能是因为在我的情况下 T 可以是一个结构体,而一个结构体是一个不可为空的类型?
            • @KristofDegrave 你是对的。这就是为什么我们必须在此处显式添加class 约束。
            • 我想给他们两个,但那是不可能的。两者都回答了我的问题,但这是我的评论得到答案的唯一答案,这就是为什么
            • 我会做以下事情:public static T? Method(T? model) where T : struct { return model ??默认(T?); }
            【解决方案7】:

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

            通过使用三元运算符或 if 语句,您可以在没有任何额外限制的情况下准确获得所需内容:

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

            【讨论】:

            • 这无法处理Nullable&lt;&gt; 类型。当modelnull 时,它返回null
            • @AlvinWong 好吧,var m = new int?() 应该是 null。对于值类型,new T() 类似于(如果不完全相同)default(T)。如果您想将可空类型初始化为默认构造函数的结果以外的其他内容,那么这段代码是不够的,但这不是 OP 的问题。
            【解决方案8】:

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

            如果您希望您的方法也适用于Nullable&lt;T&gt;,您可以为其添加重载:

            // 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);
            }
            

            【讨论】:

            • Tnx 指出这一点,但我不需要为结构值支持它:)
            • @KristofDegrave 只是为了完整性而指出。其他人可能需要它! :)
            猜你喜欢
            • 2015-12-11
            • 1970-01-01
            • 2018-04-04
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 2013-11-06
            • 2016-05-15
            • 1970-01-01
            相关资源
            最近更新 更多