c#如何找到两个对象是否相等

时间:2010-05-27 10:46:25

标签: c# comparison hash

我需要知道比较两个对象的最佳方法,并找出是否相同。我正在重写GethashCode和Equals。所以基本类看起来像:

public class Test
{
    public int Value { get; set; }
    public string String1 { get; set; }
    public string String2 { get; set; }

    public override int GetHashCode()
    {
        return Value ^ String1.GetHashCode() ^ String2.GetHashCode();
    }

    public override bool Equals( object obj )
    {
        return GetHashCode() == obj.GetHashCode();
    }
}

因此,出于测试目的,我创建了两个对象:

Test t = new Test()
{
    Value = 1,
    String1 ="One",
    String2 = "One"
};

Test t2 = new Test()
{
    Value = 1,
    String1 = "Two",
    String2 = "Two"
};

bool areEqual = t.Equals( t2 );

在测试中,这两个对象不同,所以areEqual返回true事件。我意识到这是因为String1和String2在每个对象中都是相同的值,因此在散列时会相互抵消。

有没有更好的方法可以解决哈希对象,我所拥有的方法可以解决我的问题?

6 个答案:

答案 0 :(得分:39)

您当前的等式方法已被破坏 - 值可能超过可能的哈希码。你偶尔会得到不相等的值但是给出相同的哈希是完全合理的(并且是预期的)。等于应检查实际值

public override bool Equals(object obj)
{
    Test test = obj as Test;
    if (obj == null)
    {
        return false;
    }
    return Value == test.Value &&
        String1 == test.String1 &&
        String2 == test.String2;
}

有几点需要注意:

  • 如果ValueString1相同,那么生成哈希码的方式将为任何固定String2提供相同的值;如果String1String2为空,它也会爆炸。这是使用XOR进行散列的一个不幸的方面。我更喜欢这样的东西:

    // Put this extension method in a utility class somewhere
    public static int SafeGetHashCode<T>(this T value) where T : class
    {
        return value == null ? 0 : value.GetHashCode();
    }
    
    // and this in your actual class
    public override int GetHashCode()
    {
        int hash = 19;
        hash = hash * 31 + Value;
        hash = hash * 31 + String1.SafeGetHashCode();
        hash = hash * 31 + String2.SafeGetHashCode();
        return hash;
    }
    
  • 一般来说,当涉及继承时,平等变得棘手。你可能想考虑密封你的课程。

  • 您可能还想实施IEquatable<Test>

答案 1 :(得分:16)

您的Equals不正确 - 应该定义两件事情相等的含义 - 并且具有相同的哈希码意味着相等(但是;不同的哈希码确实意味着不相等)。如果“相等”意味着“两个字符串成对相等”,则测试表示。

更好的哈希; xor因此而臭名昭着,因为通过xor得到0与自身的值是微不足道的。更好的方法可能是:

int i = 0x65407627;
i = (i * -1521134295) + Value.GetHashCode();
i = (i * -1521134295) + (String1 == null ? 0 : String1.GetHashCode());
i = (i * -1521134295) + (String2 == null ? 0 : String2.GetHashCode());
return i;

答案 2 :(得分:4)

简单

Object.Equals(obj1, obj2);

答案 3 :(得分:2)

对于任何两个对象,对象相等意味着哈希代码相等,但是,哈希代码相等并不意味着对象相等。来自MSDN上的Object.GetHashCode

  

哈希函数必须具有   以下属性:

     

如果两个对象相等,那么   每个对象的GetHashCode方法   必须返回相同的值。然而,   如果两个对象不比较   等于,GetHashCode方法   两个对象不必返回   不同的价值观。

换句话说,您的Equals写错了。它应该是这样的:

public override bool Equals(object obj)
{
    Test other = obj as Test;
    if (other == null)
        return false;

    return (Value == other.Value)
        && (String1 == other.String1)
        && (String2 == other.String2);
}

GetHashCode适用于集合(如Dictionary<K, V>)以快速确定近似相等性。 Equals用于比较两个对象是否真的相同。

答案 4 :(得分:1)

您可以将两个对象序列化为JSON,然后比较两个字符串以查看它们是否相同。

例如

JavaSriptSerializer serialiser = new JavaScriptSerializer();

string t1String = serialiser.Serialize(t);
string t2String = serialiser.Serialize(t2);

if(t1String == t2String)
   return true; //they are equal
else
   return false;

答案 5 :(得分:0)

不会是一个函数Equals总是只测试相同的类型,不应该是:

//override
    public bool Equals(Test other)//(object obj) 
    {
        //return GetHashCode() == obj.GetHashCode();
        return (Value == other.Value) &&
               (String1 == other.String1) &&
               (String2 == other.String2);
    }

问候 糟糕