在阅读StackOverflow上有关覆盖的所有问题和答案之后,GetHashCode()我编写了以下扩展方法,以便轻松方便地覆盖GetHashCode():
public static class ObjectExtensions
{
private const int _seedPrimeNumber = 691;
private const int _fieldPrimeNumber = 397;
public static int GetHashCodeFromFields(this object obj, params object[] fields) {
unchecked { //unchecked to prevent throwing overflow exception
int hashCode = _seedPrimeNumber;
for (int i = 0; i < fields.Length; i++)
if (fields[i] != null)
hashCode *= _fieldPrimeNumber + fields[i].GetHashCode();
return hashCode;
}
}
}
Run Code Online (Sandbox Code Playgroud)
(我基本上只重构了有人在那里发布的代码,因为我真的很喜欢它可以一般使用)
我用的是这样的:
public override int GetHashCode() {
return this.GetHashCodeFromFields(field1, field2, field3);
}
Run Code Online (Sandbox Code Playgroud)
你看到这段代码有什么问题吗?
我已经困惑了几天......随意拍下我的任何假设.
我们正在使用带整数键的字典.我假设在这种情况下密钥的值直接用作哈希.这是否意味着(如果密钥分组在一个小范围内)密钥哈希的分布(与密钥本身相同,对吗?)将处于类似的小范围内,因此哈希表的选择不好?
是否更好的是提供一个IEqualityComparer,用素数和模数学做一些聪明的东西来计算更好的分布式哈希?
鉴于两个不同的字符串,总是这样s.GetHashCode() != s1.GetHashCode()吗?
是不是整数的数量小于不同字符串的数量?
我有一个实现IEquatable <>的类A,使用它的字段(比如Ab和Ac)来实现/重写Equals()并覆盖GetHashCode(),并且99%的时候一切正常.A类是层次结构(B类,C类)的一部分,它们都从接口D继承; 它们都可以一起存储在字典中,因此当它们都带有自己的默认Equals()/ GetHashCode()时很方便.
然而,在构建AI时,有时需要做一些工作来获得Ab和Ac的值; 当发生这种情况时,我想存储对正在构建的实例的引用.在这种情况下,我不想使用A提供的默认Equals()/ GetHashCode()覆盖.因此,我正在考虑实现一个ReferenceEqualityComparer,这意味着强制使用Object的Equals()/ GetHashCode() :
private class ReferenceEqualityComparer<T> : IEqualityComparer<T>
{
#region IEqualityComparer<T> Members
public bool Equals(T x, T y)
{
return System.Object.ReferenceEquals(x, y);
}
public int GetHashCode(T obj)
{
// what goes here? I want to do something like System.Object.GetHashCode(obj);
}
#endregion
}
Run Code Online (Sandbox Code Playgroud)
问题是,由于A重写了Object.GetHashCode(),我如何(在A之外)调用Object.GetHashCode()作为A的实例?
当然,一种方法是A不实现IEquatable <>并且始终为我创建的任何字典提供IEqualityComparer <>,但我希望得到不同的答案.
谢谢
List<Object> listObj = new ArrayList<Object[]>();
listObj.add(new Object[]{1,"abc",new Date(21/1/2001)});
listObj.add(new Object[]{1,"abc",new Date(21/1/2001)});
listObj.add(new Object[]{2,"acc",new Date(21/1/2001)});
Set<Object[]> unique = new HashSet<Object[]>();
unique.addAll();
Run Code Online (Sandbox Code Playgroud)
我期待得到:
{1,abc,21/1/2001},{2,acc,21/1/2001}
Run Code Online (Sandbox Code Playgroud)
相反,我得到:
{1,abc,21/1/2001},{1,abc,(21/1/2001},{2,acc,21/1/2001}
Run Code Online (Sandbox Code Playgroud)
如何在此示例中查找唯一条目?
以下代码可以吗?
public override bool Equals(object obj)
{
if (obj == null || !(obj is LicenseType))
return false;
return GetHashCode() == obj.GetHashCode();
}
public override int GetHashCode()
{
return
Vendor.GetHashCode() ^
Version.GetHashCode() ^
Modifiers.GetHashCode() ^
Locale.GetHashCode();
}
Run Code Online (Sandbox Code Playgroud)
所有属性都是枚举/数字字段,并且是唯一定义LicenseType对象的属性.
c# ×5
gethashcode ×3
.net ×2
hash ×2
dictionary ×1
equals ×1
hashcode ×1
hashset ×1
iequatable ×1
java ×1
unique ×1