【问题标题】:Having problems comparing two custom class objects [duplicate]比较两个自定义类对象时遇到问题[重复]
【发布时间】:2025-12-18 22:30:01
【问题描述】:

可能重复:
What is “Best Practice” For Comparing Two Instances of a Reference Type?

我的应用程序有这个自定义类。这个类有两个实例(A 和 B),我试图比较它们。但是,我遇到了问题;我正在实现IEquatable<T> 接口来进行此比较,使用覆盖的Equals 方法。

Equals 方法调用了 ReferenceEquals 函数,这是不正常的。

这里是测试用例:

案例 1: A 和 B 是不同的实例,包含不同的数据.. ReferenceEquals 说:它们是不同的(这是正确的!)

案例 2: A 和 B 是不同的实例,但 B 是使用 A 的变量值实例化的(即 A 和 B 都包含完全相同的数据!)..ReferenceEquals 说:它们是不同(这是错误的!)

案例 3: A 和 B 是 相同 实例(即 A 被传入两次,例如 Equals (A, A)ReferenceEquals 说:它们是相同的(这是正确的!)

那么如何让案例 2 的结果也正确呢?

实现IEquatable<T>的类:

namespace DBtestApp1
{
    class QuantityBasedDiscount : IEquatable<QuantityBasedDiscount>
    {
        public string pType { get; set; }
        public string pSubType { get; set; }
        public DataTable quantityDiscountsDT { get; set; }

        public QuantityBasedDiscount()
        {
            pType = "";
            pSubType = "";
            quantityDiscountsDT = new DataTable();
        }

        public QuantityBasedDiscount(string iProdType, string iProdSubType, DataTable iQuantitiesDT)
        {
            pType = iProdType;
            pSubType = iProdSubType;
            quantityDiscountsDT = iQuantitiesDT;
        }

        public override int GetHashCode()
        {
            return base.GetHashCode();
        }

        public override bool Equals(Object obj)
        {

            var other = obj as QuantityBasedDiscount;
            if (other == null) return false;

            return Equals(other);
        }

        public bool Equals(QuantityBasedDiscount other)
        {
            if (other == null)
            {
                return false;
            }

            if (ReferenceEquals(this, other))
            {
                return true;
            }

            return false;
        }
    }
}

调用Equals方法的代码(此处为案例2配置):

private bool AnyUnsavedChanges()
{
    QuantityBasedDiscount copyB = new QuantityBasedDiscount(copyA.pType, copyA.pSubType, copyA.quantityDiscountsDT);

    if (copyA.Equals(copyB))
    {
         return false; //They are the same!
    }
    else
    {
         return true; //They are NOT the same!
    }

}

那么这段代码有什么问题呢?

【问题讨论】:

  • 我不明白案例2。"...包含完全相同的数据。ReferenceEquals 说:它们是不同的,这是错误的" ReferenceEquals 确定指定的 Object 实例是否为相同的实例,而不是如果它具有相同的值。
  • 哦,我明白了……对于实例不同但值相同的情况,我该如何进行这样的比较?我认为 ReferenceEquals 也可以处理这种情况..
  • @Ahmad:您必须手动处理它,通过将当前对象字段与其他对象字段进行比较...这就是覆盖Equals(object other)...的目的...
  • 单独比较字段将是一项极其困难的任务,我希望以某种方式避免这种情况!我定义的许多其他类也需要这种实例比较功能,包含很多字段,其数据类型是复杂的结构......肯定有一些方法可以进行这样的类实例比较?
  • @Ahmad:不幸的是你不能。也许 resharper 或其他一些工具可以自动创建此比较的代码,但没有内置函数可以为类(引用类型)执行此操作。值类型天生就是这样实现的,但不建议将具有很多字段的对象实现为结构体......

标签: c# compare equals equality iequatable


【解决方案1】:

虽然不是完全重复,但您可以在这里找到所有答案:What is "Best Practice" For Comparing Two Instances of a Reference Type?。从该线程中获取 sn-p 提供的 Konrad 答案,以免出错。


简而言之,你做错了。您没有比较通用 Equals 方法中的实际值。此外,在 Equals 方法中调用 == 运算符也不安全。这样做:

public override int GetHashCode()
{
    return pType.GetHashCode() ^ pSubType.GetHashCode() ^ quantityDiscountsDT.GetHashCode();
    //or something similar, but fast.
}

public bool Equals(QuantityBasedDiscount other)
{
   if (ReferenceEquals(null, other))
    {
        return false;
    }

    if (ReferenceEquals(this, other))
    {
        return true;
    }

    return pType == other.pType && pSubType == other.pSubType && 
           quantityDiscountsDT == other.quantityDiscountsDT;
}

如果您的 DataTable 字段被修改,这可能仍然会给您带来不一致的结果。这一切都取决于如何为 DataTable 实现 == 运算符。要对此进行更多控制,您必须派生自己的 DataTable..

此外,您可能还想重载 ==!= 运算符。对于所有检查提供的链接。

【讨论】:

    【解决方案2】:

    您必须重写 Equals 和 GetHashCode,如果您喜欢/需要语法,您还需要重载 '==' 和 '!=' 运算符。在覆盖 Equals 时,您可以首先检查 ReferenceEquals 是否返回 true,如果不是,则比较对象的内容。

    我个人更喜欢在这种情况下避免使用 ReferenceEquals。

    【讨论】: