有什么用GetHashCode()?我可以使用GetHashCode()?跟踪对象标识吗?如果是这样,你能提供一个例子吗?
public class Foo
{
public int X { get; set; }
public int Y { get; set; }
public int Z { get; set; }
public override int GetHashCode()
{
var hash = 17;
hash *= 23 + x.GetHashCode();
hash *= 23 + y.GetHashCode();
hash *= 23 + z.GetHashCode();
}
}
Run Code Online (Sandbox Code Playgroud)
当你去单元测试GetHashCode时,我在计算原始组件和重复函数或使用预定值之间徘徊:
[TestMethod]
public void Test1
{
var x = 1; y = 2; z = 3;
var foo = new Foo() { X = x, Y = y, Z …Run Code Online (Sandbox Code Playgroud) 我想List通过使用IEqualityComparer接口从C# 中获取不同的项目。但我不知道GetHashCode. 我已经实现了GetHashCode和Equals方法。以及如何调用Equals方法从具有用户定义数据类型的列表中获取不同的项目。
在一些C#代码中,我使用linq GroupBy<TSource, TKey>()自定义方法IEqualityComparer<T>.
GroupBy(x => x.SomeField, new FooComparer());
Run Code Online (Sandbox Code Playgroud)
我用作分组键的字段可以是null.因此,我不得不null在Equals()方法中添加一些检查:
public bool Equals(Foo x, Foo y)
{
if (x == null && y == null)
return true;
else if (x == null && y != null)
return false;
else if (x != null && y == null)
return false;
else
return x.Id == y.Id;
}
Run Code Online (Sandbox Code Playgroud)
问题是:我应该在GetHashCode()功能上做同样的事情吗?
public int GetHashCode(Foo obj)
{
if (obj == null) //is this really needed …Run Code Online (Sandbox Code Playgroud) 我在网上遇到过几个代码看起来像这样的地方:
[<CustomEquality;NoComparison>]
type Test =
| Foo
| Bar
override x.Equals y =
match y with
| :? Test as y' ->
match y' with
| Foo -> false
| Bar -> true // silly, I know, but not the question here
| _ -> failwith "error" // don't do this at home
override x.GetHashCode() = hash x
Run Code Online (Sandbox Code Playgroud)
但是当我在FSI中运行上面的操作时,当我调用hash foo实例Test或foo.GetHashCode()直接调用时,提示不会返回.
let foo = Test.Foo;;
hash foo;; // no returning to the console until Ctrl-break …Run Code Online (Sandbox Code Playgroud) 我最近发现 Visual Studio 2017 可以为Equalsand自动生成覆盖GetHashCode,但我想知道为什么该GetHashCode实现不在未经检查的块中?
我用两个公共字符串属性 Foo 和 Bar 创建了一个简单的类,生成的GetHashCode实现如下所示。
public override int GetHashCode()
{
var hashCode = -504981047;
hashCode = hashCode * -1521134295 + EqualityComparer<string>.Default.GetHashCode(Foo);
hashCode = hashCode * -1521134295 + EqualityComparer<string>.Default.GetHashCode(Bar);
return hashCode;
}
Run Code Online (Sandbox Code Playgroud)
我的印象是未经检查的GetHashCode实现很重要,因为它很可能会溢出,而且我们不希望出现任何溢出异常,因为如果它环绕就可以了。
Delphi 2009将GetHashCode函数添加到TObject.GetHashCode返回一个Integer,用于在TDictionary中进行散列.
如果希望对象在TDictionary中正常工作,则需要适当地重写GetHashCode,以便通常不同的对象返回不同的整数哈希码.
但是你对包含双字段的对象做了什么?如何将这些double值转换为GetHashCode的整数?
例如,它通常在Java中完成的方式是使用Double.doubleToLongBits或Float.floatToIntBits之类的方法.后者的文档描述如下:"根据IEEE 754浮点"单格式"位布局返回指定浮点值的表示." 这涉及对浮点值的不同位使用不同掩码的一些按位操作.
在Delphi中有没有这样做的功能?
首先,我在这里使用所GetHashCode描述的算法.现在,想象下面的(人为的)示例:
class Foo
{
public Foo(int intValue, double doubleValue)
{
this.IntValue = intValue;
this.DoubleValue = doubleValue;
}
public int IntValue { get; private set; }
public double DoubleValue { get; private set; }
public override int GetHashCode()
{
unchecked
{
int hash = 17;
hash = hash * 23 + IntValue.GetHashCode();
hash = hash * 23 + DoubleValue.GetHashCode();
return hash;
}
}
}
class DerivedFoo : Foo
{
public DerivedFoo(int intValue, double doubleValue)
: base(intValue, doubleValue) …Run Code Online (Sandbox Code Playgroud) 我的程序创建自定义对象,我想获得一个独特的列表.所以我想使用一个集合并按对象添加对象.该集将防止重复.最后我有一组独特的对象.
我通常会使用HashSet,因为我不需要排序集.只有,有很多不同的潜在对象.超过2 ^ 32.GetHashCode函数返回一个int,因此这不能作为我的对象的唯一键.
我假设我不能使用HashSet,因此必须使用较慢的SortedSet并让我的对象实现IComparable/CompareTo.它是否正确?或者有一种方法来使用具有长哈希码的HashSet吗?
在下面的StackOverflow 问题中, Jon Skeets的回答指出了一个很好的实现是......
// Note: Not quite FNV!
public override int GetHashCode()
{
unchecked // Overflow is fine, just wrap
{
int hash = (int) 2166136261;
// Suitable nullity checks etc, of course :)
hash = (hash * 16777619) ^ bool1.GetHashCode();
hash = (hash * 16777619) ^ bool2.GetHashCode();
return hash;
}
}
Run Code Online (Sandbox Code Playgroud)
如果两个字段都是bool怎么办?这仍然是一个很好的实现还是会有点矫枉过正?如果这有点过分,那么GetHashCode当所有字段都是bool类型时,推荐的实现方法是什么?
在我的情况下,我只比较两个布尔.