如何解决算子'!='不能应用于'T'和'T'类型的操作数

Dar*_*arf 100 c# generics

此代码段按预期的int类型工作:

public class Test 
{
    public int Value
    {
        get => _Value;
        set
        {
            if (_Value != value)
                _Value = value;
        }
    }
    private int _Value;
}
Run Code Online (Sandbox Code Playgroud)

int被泛型替换时T,编译器抱怨:

运算符'!='不能应用于'T'和'T'类型的操作数

为什么会发生这种情况并且有办法解决它?

Meh*_*dad 136

using System.Collections.Generic;

public class Test<T>
{
    public T Value
    {
         get => _Value; 
         set
         {
            // operator== is undefined for generic T; EqualityComparer solves this
            if (!EqualityComparer<T>.Default.Equals(_Value, value))
            {
                _Value = value;
            }
         }
    }
    private T _Value;
}
Run Code Online (Sandbox Code Playgroud)

  • 我无法相信我的答案能够在一年半的时间里存活下来,没有人指出这个巨大的错字...... (8认同)
  • @CodesInChaos:是的我想知道现在有多少人在他们的代码中使用了错误的方法...... (5认同)
  • 您能否为此代码解决问题的原因添加一些解释? (5认同)
  • @Mehrdad,我会使用`public class Test <T>,其中T:IEquatable <T>`然后调用`_Value.Equals(value)`,这将是语义更严格的,因为它不再是一个实现细节而是一个类宣言. (4认同)
  • @Mehrdad我刚才添加了上面的评论,但我假设我不明白你的代码是如何通过查看代码来解决问题的.为了改进这个答案,我会在答案中添加一个句子来解释你刚才提到的,你可以通过避免使用`==`运算符解决问题. (3认同)

gdo*_*ica 80

T是一个类型参数,可以是a class或a struct,因此编译器不允许您执行类和结构中不存在的操作.

结构体默认情况下没有==和!=(但可以添加),这就是编译器抱怨的原因.

如果使用where关键字向type参数添加约束,则编译器将允许您使用该类型\ interface method \运算符

约束T成为一个class

public class Test<T> where T : class
{
     public T Value
     {
         private T _Value;

         get { return _Value; }
         set
         {
             if (_value != value)
                 _Value = value;             
         }
     }
}
Run Code Online (Sandbox Code Playgroud)

或者只是使用Equals而不是==操作员

public class Test<T>
{
     public T Value
     {
         private T _Value;

         get { return _Value; }
         set
         {
             if (!_value.Equals(value)
                 _Value = value;             
         }
     }
}
Run Code Online (Sandbox Code Playgroud)

  • 在第二个示例中,如果_value为null,则将抛出`NullReferenceException`。最好在需要支持结构的地方使用Mehrdad的示例。 (2认同)

lep*_*pie 24

T可以是任何类型.除非在(struct)类型上定义了这样的运算符,否则不能在结构上使用==/ !=.

  • 这当然与这个问题有关,至少现在如此. (5认同)
  • 虽然与问题无关,但我发现这很有帮助。 (2认同)