gpt4 book ai didi

C# - 类的通用 HashCode 实现

转载 作者:可可西里 更新时间:2023-11-01 09:03:22 25 4
gpt4 key购买 nike

我正在研究如何为一个类构建最好的 HashCode,并且我看到了一些算法。我看到了这个:Hash Code implementation , 似乎.NET 类的 HashCode 方法是相似的(通过反射代码查看)。

那么问题来了,为什么不创建上面的静态类来自动构建 HashCode,只是通过传递我们认为是“键”的字段。

// Old version, see edit
public static class HashCodeBuilder
{
public static int Hash(params object[] keys)
{
if (object.ReferenceEquals(keys, null))
{
return 0;
}

int num = 42;

checked
{
for (int i = 0, length = keys.Length; i < length; i++)
{
num += 37;
if (object.ReferenceEquals(keys[i], null))
{ }
else if (keys[i].GetType().IsArray)
{
foreach (var item in (IEnumerable)keys[i])
{
num += Hash(item);
}
}
else
{
num += keys[i].GetHashCode();
}
}
}

return num;
}
}

然后像这样使用它:

// Old version, see edit
public sealed class A : IEquatable<A>
{
public A()
{ }

public string Key1 { get; set; }
public string Key2 { get; set; }
public string Value { get; set; }

public override bool Equals(object obj)
{
return this.Equals(obj as A);
}

public bool Equals(A other)
{
if(object.ReferenceEquals(other, null))
? false
: Key1 == other.Key1 && Key2 == other.Key2;
}

public override int GetHashCode()
{
return HashCodeBuilder.Hash(Key1, Key2);
}
}

总是自己的方法会简单得多,不是吗?我错过了什么?


编辑

根据所有评论,我得到以下代码:

public static class HashCodeBuilder
{
public static int Hash(params object[] args)
{
if (args == null)
{
return 0;
}

int num = 42;

unchecked
{
foreach(var item in args)
{
if (ReferenceEquals(item, null))
{ }
else if (item.GetType().IsArray)
{
foreach (var subItem in (IEnumerable)item)
{
num = num * 37 + Hash(subItem);
}
}
else
{
num = num * 37 + item.GetHashCode();
}
}
}

return num;
}
}


public sealed class A : IEquatable<A>
{
public A()
{ }

public string Key1 { get; set; }
public string Key2 { get; set; }
public string Value { get; set; }

public override bool Equals(object obj)
{
return this.Equals(obj as A);
}

public bool Equals(A other)
{
if(ReferenceEquals(other, null))
{
return false;
}
else if(ReferenceEquals(this, other))
{
return true;
}

return Key1 == other.Key1
&& Key2 == other.Key2;
}

public override int GetHashCode()
{
return HashCodeBuilder.Hash(Key1, Key2);
}
}

最佳答案

您的 Equals 方法已损坏 - 它假设具有相同哈希码的两个对象必然相等。事实并非如此。

您的哈希码方法乍一看还不错,但实际上可以做一些工作 - 见下文。这意味着装箱任何值类型值 在您调用它时创建一个数组,但除此之外没关系(正如 SLaks 指出的那样,集合处理存在一些问题)。您可能需要考虑编写一些通用重载,以避免常见情况下的性能损失(可能是 1、2、3 或 4 个参数)。您可能还想使用 foreach 循环而不是普通的 for 循环,只是为了惯用。

您可以为平等做同样的事情,但它会稍微困难和困惑一些。

编辑:对于哈希码本身,您只是在添加值。我怀疑你正试图做这种事情:

int hash = 17;
hash = hash * 31 + firstValue.GetHashCode();
hash = hash * 31 + secondValue.GetHashCode();
hash = hash * 31 + thirdValue.GetHashCode();
return hash;

但是散列乘以 31,它不会 31。目前,对于相同的值,您的散列码将始终返回相同的值,无论它们是否顺序相同,这并不理想。

编辑:哈希码的用途似乎有些困惑。我建议不确定的人阅读 Object.GetHashCode 的文档然后是 Eric Lippert 的 blog post about hashing and equality .

关于C# - 类的通用 HashCode 实现,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/5450696/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com