确定两个实例是否相同,但两个属性除外

时间:2015-11-19 11:40:39

标签: c# object comparison equals

我有一个包含十个属性的类,我正在寻找在这些属性中具有相同值的对象,但两个特定属性除外。

我想扩展一个具有我想要比较的八个属性的基类,然后扩展这个基类,调用基本Equals方法?

决定这一点的代码密集程度最低的是什么?

1 个答案:

答案 0 :(得分:0)

每当您希望比较自定义类的两个实例的值相等(即两个具有相同值或值的对象)而不是参考质量(两个对象引用引用相同的底层对象)时,您必须在对象的设计中考虑到了。有一个pattern you can follow to do this。简而言之,它涉及实现System.IEquatable<T>接口,该接口定义了带有签名bool Equals(MyClass other)的方法。当true具有相同的“值”为other对象时,您可以实现此方法以返回this。以下是简单对象的基本示例,该对象具有4个确定其值相等的属性:

class MyClass : IEquatable<MyClass>
{
    public int ImportantProperty1 { get; set; }
    public int ImportantProperty2 { get; set; }
    public int ImportantProperty3 { get; set; }
    public int ImportantProperty4 { get; set; }
    public int NonImportantProperty { get; set; }

    public bool Equals(MyClass other)
    {
        return
            (!Object.ReferenceEquals(this, null)) &&
            (this.ImportantProperty1 == other.ImportantProperty1) &&
            (this.ImportantProperty2 == other.ImportantProperty2) &&
            (this.ImportantProperty3 == other.ImportantProperty3) &&
            (this.ImportantProperty4 == other.ImportantProperty4);
    }
}

使用上面的代码,您将能够执行以下操作:

MyClass a = new MyClass() { };
MyClass b = new MyClass() { };
if (a.Equals(b))
    Console.WriteLine("a and b are equal");

这是最低限度的。但是,如链接文章中所述,您可能需要考虑以下优化:

  1. 重写virtual Object.Equals(Object)方法,以便调用特定于类型的Equals方法。这样您就可以将MyClass与其他类型的对象进行比较:

    public override bool Equals(object obj)
    {
        return this.Equals(obj as MyClass);
    }
    
  2. 添加到bool Equals(MyClass)方法检查以查看other是否引用与this相同的对象:

        public bool Equals(MyClass other)
        {
            if (Object.ReferenceEquals(this, other))
                return true;    
    
            return
                (!Object.ReferenceEquals(this, null)) &&
                (this.ImportantProperty1 == other.ImportantProperty1) &&
                (this.ImportantProperty2 == other.ImportantProperty2) &&
                (this.ImportantProperty3 == other.ImportantProperty3) &&
                (this.ImportantProperty4 == other.ImportantProperty4);
        }
    
  3. 覆盖Object.GetHashCode()方法,以便两个具有值相等的对象生成相同的哈希代码。这是我在这种情况下实现此方法时使用的模式:

    public override int GetHashCode()
    {
        unchecked {
            int hash = 17;
            hash = hash * 23 + ImportantProperty1.GetHashCode();
            hash = hash * 23 + ImportantProperty2.GetHashCode();
            hash = hash * 23 + ImportantProperty3.GetHashCode();
            hash = hash * 23 + ImportantProperty4.GetHashCode();
            return hash;
        }
    }
    
  4. 可选择覆盖==!=运算符。除非这些被覆盖,否则它们将默认引用相等。有关示例,请参阅链接的文章。

  5. 以下是我的完整示例:

    namespace ValueEquality
    {
    
        class MyClass : IEquatable<MyClass>
        {
            public int ImportantProperty1 { get; set; }
            public int ImportantProperty2 { get; set; }
            public int ImportantProperty3 { get; set; }
            public int ImportantProperty4 { get; set; }
            public int NonImportantProperty { get; set; }
    
            public bool Equals(MyClass other)
            {
                if (Object.ReferenceEquals(this, other))
                    return true;    
    
                return
                    (!Object.ReferenceEquals(this, null)) &&
                    (this.ImportantProperty1 == other.ImportantProperty1) &&
                    (this.ImportantProperty2 == other.ImportantProperty2) &&
                    (this.ImportantProperty3 == other.ImportantProperty3) &&
                    (this.ImportantProperty4 == other.ImportantProperty4);
            }
    
            public override bool Equals(object obj)
            {
                return this.Equals(obj as MyClass);
            }
    
            public override int GetHashCode()
            {
                unchecked {
                    int hash = 17;
                    hash = hash * 23 + ImportantProperty1.GetHashCode();
                    hash = hash * 23 + ImportantProperty2.GetHashCode();
                    hash = hash * 23 + ImportantProperty3.GetHashCode();
                    hash = hash * 23 + ImportantProperty4.GetHashCode();
                    return hash;
                }
            }
        }
    
        class Program
        {
            static void Main(string[] args)
            {
                MyClass a = new MyClass() { };
                MyClass b = new MyClass() { };
                if (a.Equals(b))
                    Console.WriteLine("a and b are equal");
            }
        }
    }