我需要知道比较两个对象的最佳方法,并找出是否相同。我正在重写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在每个对象中都是相同的值,因此在散列时会相互抵消。
有没有更好的方法可以解决哈希对象,我所拥有的方法可以解决我的问题?
答案 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;
}
有几点需要注意:
如果Value
和String1
相同,那么生成哈希码的方式将为任何固定String2
提供相同的值;如果String1
或String2
为空,它也会爆炸。这是使用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);
}
问候 糟糕