如何比较相同但未受限制的泛型类型的两个元素是否相等?

10

可能重复:
在C#中不能将运算符==应用于泛型类型吗?

我有以下通用类,编译器抱怨"运算符'!='不能应用于类型为'TValue'和'TValue'的操作数"(参见CS0019):

public class Example<TValue>
{
    private TValue _value;
    public TValue Value
    {
        get { return _value; }
        set
        {
            if (_value != value) // <<-- ERROR
            {
                _value= value;
                OnPropertyChanged("Value");
            }
        }
    }
}

如果我将 TValue 限制为 class,我可以使用 Object.Equals()。但由于我需要在结构体和类中都使用它,如果能够避免这种情况,我会非常高兴。
因此问题是,如何比较同一但未受限制的泛型类型的两个元素是否相等?

2
为什么不能在值类型中使用.Equals方法? - Lasse V. Karlsen
默认情况下,如果在引用类型上调用“object.Equals(a, b)”,那么将调用“object.ReferenceEquals(a, b)”函数。 - TcKs
@TcKs:默认情况下,您无法确定在派生类中是否已重写Equals。 - leppie
@Iepie:是的,如果重写了等于运算符(和Equals方法),那么这些方法应该比默认实现更好地知道如何比较两个对象。因此,它应该返回正确的结果。 - TcKs
@Tcks:没错,是我犯了个愚蠢的错误 :) - leppie
6个回答

15

你尝试过像这样的东西吗?

public class Example<TValue>
{
    private TValue _value;
    public TValue Value
    {
        get { return _value; }
        set
        {

            if (!object.Equals(_value, value))
            {
                _value = value;
                OnPropertyChanged("Value");
            }
        }
    }
}

http://msdn.microsoft.com/en-us/library/w4hkze5k.aspx 表示默认情况下,值类型将按位进行比较,否则将使用 Equals() 方法。这正是我要找的。 - David Schmitt
5
请注意,这将对值类型造成装箱惩罚。 - Jon Skeet

7

三个选项:

  • 将 TValue 约束为实现 IEquatable<TValue>,然后调用 x.Equals(y)
  • 使用另一个类型为 IEqualityComparer<TValue> 的参数并使用它
  • 使用 EqualityComparer<TValue>.Default 执行比较

当然,您可以随时混合和匹配选项2和3 - 默认使用默认比较器,但也允许提供特定的比较器。


2
  • 对于值类型,使用Equals()方法
  • 对于引用类型,使用ReferenceEquals()方法

1
我宁愿避免反射或以其他方式区分这两种情况。目前,我正在使用一个抽象基类并实现这些位两次 :-/ - David Schmitt
你使用了哪种反射?执行 typeof(TValue) 是一个编译时常量,检查该类型不会真正产生任何成本。 - leppie

1

是否可以使用IComparable接口?

public class Example<TValue> where TValue: IComparable
{
    private TValue _value;
    public TValue Value
    {
        get { return _value; }
        set
        {

            if (_value.CompareTo(value) != 0)
            {
                _value = value;
                OnPropertyChanged("Value");
            }
        }
    }
}

0
public static bool operator ==(EntityBase<T> entity1, EntityBase<T> entity2)
        {
            if ((object)entity1 == null && (object)entity2 == null)
            {
                return true;
            }

            if ((object)entity1 == null || (object)entity2 == null)
            {
                return false;
            }

            if (Comparer<T>.Default.Compare(entity1.Id, entity2.Id) != 0)
            {
                return false;
            }

            return true;
        }

0

我认为在这里不能使用!=运算符,因为有些情况下它无法使用。例如,除非重载比较运算符(== !=),否则不能用!=来比较结构体。

当然,您可以比较语言结构,如int != int,但我不确定这是如何实现的。

因此,由于TValue可能是一个自定义结构体,所以不能使用!=运算符。


是的,这也是我对CS0019的理解。 - David Schmitt

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接