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

lan*_*der 30 c# hash comparison

我需要知道比较两个对象的最佳方法,并找出是否相等.我正在重写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();
    }
}
Run Code Online (Sandbox Code Playgroud)

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

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 );
Run Code Online (Sandbox Code Playgroud)

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

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

Jon*_*eet 40

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

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;
}
Run Code Online (Sandbox Code Playgroud)

有几点需要注意:

  • 您生成哈希码的方式将为任何固定的Valueif 提供相同的值,String1并且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;
    }
    
    Run Code Online (Sandbox Code Playgroud)
  • 一般来说,当涉及继承时,平等变得棘手.你可能想考虑密封你的课程.

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

  • Re`SafeGetHashCode` - 只是提到`EqualityComparer <T> .GetHashCode`会做一些非常相似的事情 - 虽然扩展方法非常整洁; p (2认同)

Mar*_*ell 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;
Run Code Online (Sandbox Code Playgroud)


小智 5

简单

Object.Equals(obj1, obj2);
Run Code Online (Sandbox Code Playgroud)

  • 这完全取决于 obj1/obj2 是否是引用类型。请参阅http://msdn.microsoft.com/en-us/library/bsc2ak47.aspx (2认同)