base.GetHashCode() 是如何为结构实现的?
How is base.GetHashCode() implemented for a struct?
我最近在 struct
中看到这段代码,我想知道 base.GetHashCode
到底做了什么。
public override int GetHashCode()
{
var hashCode = -592410294;
hashCode = hashCode * -1521134295 + base.GetHashCode();
hashCode = hashCode * -1521134295 + m_Value.GetHashCode();
return hashCode;
}
一个结构体的基础class是ValueType
class,源码在网上。他们很有帮助地留下了描述其工作原理的评论:
/*=================================GetHashCode==================================
**Action: Our algorithm for returning the hashcode is a little bit complex. We look
** for the first non-static field and get it's hashcode. If the type has no
** non-static fields, we return the hashcode of the type. We can't take the
** hashcode of a static member because if that member is of the same type as
** the original type, we'll end up in an infinite loop.
**Returns: The hashcode for the type.
**Arguments: None.
**Exceptions: None.
==============================================================================*/
[System.Security.SecuritySafeCritical] // auto-generated
[ResourceExposure(ResourceScope.None)]
[MethodImplAttribute(MethodImplOptions.InternalCall)]
public extern override int GetHashCode();
coreclr 仓库有 this comment:
Action: Our algorithm for returning the hashcode is a little bit complex. We look
for the first non-static field and get it's hashcode. If the type has no
non-static fields, we return the hashcode of the type. We can't take the
hashcode of a static member because if that member is of the same type as
the original type, we'll end up in an infinite loop.
但是,代码不存在,看起来 完全 不是这样。示例:
using System;
struct Foo
{
public string x;
public string y;
}
class Test
{
static void Main()
{
Foo foo = new Foo();
foo.x = "x";
foo.y = "y";
Console.WriteLine(foo.GetHashCode());
Console.WriteLine("x".GetHashCode());
Console.WriteLine("y".GetHashCode());
}
}
我盒子上的输出:
42119818
372029398
372029397
更改 y
的值似乎不会更改 foo
的哈希码。
但是,如果我们将字段设为 int
值,那么第一个字段会影响输出。
简而言之:这很复杂,您可能不应该依赖它在运行时的多个版本中保持不变。除非您真的非常有信心不需要将自定义结构用作基于散列的 dictionary/set 中的键,否则我强烈建议覆盖 GetHashCode
和 Equals
(并实施 IEquatable<T>
以避免装箱)。
我最近在 struct
中看到这段代码,我想知道 base.GetHashCode
到底做了什么。
public override int GetHashCode()
{
var hashCode = -592410294;
hashCode = hashCode * -1521134295 + base.GetHashCode();
hashCode = hashCode * -1521134295 + m_Value.GetHashCode();
return hashCode;
}
一个结构体的基础class是ValueType
class,源码在网上。他们很有帮助地留下了描述其工作原理的评论:
/*=================================GetHashCode==================================
**Action: Our algorithm for returning the hashcode is a little bit complex. We look
** for the first non-static field and get it's hashcode. If the type has no
** non-static fields, we return the hashcode of the type. We can't take the
** hashcode of a static member because if that member is of the same type as
** the original type, we'll end up in an infinite loop.
**Returns: The hashcode for the type.
**Arguments: None.
**Exceptions: None.
==============================================================================*/
[System.Security.SecuritySafeCritical] // auto-generated
[ResourceExposure(ResourceScope.None)]
[MethodImplAttribute(MethodImplOptions.InternalCall)]
public extern override int GetHashCode();
coreclr 仓库有 this comment:
Action: Our algorithm for returning the hashcode is a little bit complex. We look for the first non-static field and get it's hashcode. If the type has no non-static fields, we return the hashcode of the type. We can't take the hashcode of a static member because if that member is of the same type as the original type, we'll end up in an infinite loop.
但是,代码不存在,看起来 完全 不是这样。示例:
using System;
struct Foo
{
public string x;
public string y;
}
class Test
{
static void Main()
{
Foo foo = new Foo();
foo.x = "x";
foo.y = "y";
Console.WriteLine(foo.GetHashCode());
Console.WriteLine("x".GetHashCode());
Console.WriteLine("y".GetHashCode());
}
}
我盒子上的输出:
42119818
372029398
372029397
更改 y
的值似乎不会更改 foo
的哈希码。
但是,如果我们将字段设为 int
值,那么第一个字段会影响输出。
简而言之:这很复杂,您可能不应该依赖它在运行时的多个版本中保持不变。除非您真的非常有信心不需要将自定义结构用作基于散列的 dictionary/set 中的键,否则我强烈建议覆盖 GetHashCode
和 Equals
(并实施 IEquatable<T>
以避免装箱)。