C#HashCode Builder

我以前经常使用apache哈希码构建器

这是否适用于C#

我使用以下内容:

public static int ComputeHashFrom(params object[] obj) { ulong res = 0; for(uint i=0;i> 32)); } 

使用这样的帮助是快速,简单和可靠的,但它有潜在的两个缺点(你不太经常遇到,但很高兴知道):

  • 它可以为一些参数的分布生成差的哈希码。 例如,对于任何int xComputeHashFrom(x*-3, x) == 0 – 因此,如果您的对象具有某些病理属性,则可能会遇到许多哈希代码冲突,从而导致字典和散列表不佳。 它不太可能发生,但类型感知哈希码计算可以更容易地避免这些问题。
  • 哈希码的计算比专门的计算慢。 特别是,它涉及params数组和循环的分配 – 如果你只有两个成员要处理,这会产生相当多的不必要的开销。

这些缺点都不会导致任何错误,仅仅是效率低下; 并且在此方法或哈希码使用者的内部中,在分析器中显示为blips。

这是我自制的建筑师。

用法:

 hash = new HashCodeBuilder(). Add(a). Add(b). Add(c). Add(d). GetHashCode(); 

abcd类型字段无关紧要,易于扩展,无需创建数组。

资源:

 public sealed class HashCodeBuilder { private int hash = 17; public HashCodeBuilder Add(int value) { unchecked { hash = hash * 31 + value; //see Effective Java for reasoning // can be any prime but hash * 31 can be opimised by VM to hash << 5 - hash } return this; } public HashCodeBuilder Add(object value) { return Add(value != null ? value.GetHashCode() : 0); } public HashCodeBuilder Add(float value) { return Add(value.GetHashCode()); } public HashCodeBuilder Add(double value) { return Add(value.GetHashCode()); } public override int GetHashCode() { return hash; } } 

样品用法:

 public sealed class Point { private readonly int _x; private readonly int _y; private readonly int _hash; public Point(int x, int y) { _x = x; _y = y; _hash = new HashCodeBuilder(). Add(_x). Add(_y). GetHashCode(); } public int X { get { return _x; } } public int Y { get { return _y; } } public override bool Equals(object obj) { return Equals(obj as Point); } public bool Equals(Point other) { if (other == null) return false; return (other._x == _x) && (other._y == _y); } public override int GetHashCode() { return _hash; } } 

C#没有内置的HashCode构建器,但您可以自己滚动。 我最近有这个精确的问题并创建了这个哈希码生成器,它不使用装箱,使用generics,并实现了一个修改的FNV算法来生成特定的哈希。 但是你可以使用任何你想要的算法,比如System.Security.Cryptography

  public static int GetHashCode(params T[] args) { return args.GetArrayHashCode(); } public static int GetArrayHashCode(this T[] objects) { int[] data = new int[objects.Length]; for (int i = 0; i < objects.Length; i++) { T obj = objects[i]; data[i] = obj == null ? 1 : obj.GetHashCode(); } return GetFnvHash(data); } private static int GetFnvHash(int[] data) { unchecked { const int p = 16777619; long hash = 2166136261; for (int i = 0; i < data.Length; i++) { hash = (hash ^ data[i]) * p; } hash += hash << 13; hash ^= hash >> 7; hash += hash << 3; hash ^= hash >> 17; hash += hash << 5; return (int)hash; } }