浏览string.GetHashCode
使用Reflector的源代码会显示以下内容(对于mscorlib.dll版本4.0):
public override unsafe int GetHashCode()
{
fixed (char* str = ((char*) this))
{
char* chPtr = str;
int num = 0x15051505;
int num2 = num;
int* numPtr = (int*) chPtr;
for (int i = this.Length; i > 0; i -= 4)
{
num = (((num << 5) + num) + (num >> 0x1b)) ^ numPtr[0];
if (i <= 2)
{
break;
}
num2 = (((num2 << 5) + num2) + (num2 >> 0x1b)) ^ numPtr[1]; …
Run Code Online (Sandbox Code Playgroud) 考虑以下代码:
Console.WriteLine("Hello, World!".GetHashCode());
Run Code Online (Sandbox Code Playgroud)
第一次运行:
139068974
第二次运行:
-263623806
现在考虑用 Kotlin 编写的相同内容:
println("Hello, World!".hashCode())
Run Code Online (Sandbox Code Playgroud)
第一次运行:
1498789909
第二次运行:
1498789909
为什么string
.NET 中的每次执行的哈希码都会发生变化,但在其他运行时(如 JVM)上却不会发生变化?
我正在使用域模型,并且正在思考我们在.NET中实现这两种方法的各种方法.你最喜欢的策略是什么?
这是我目前的实施:
public override bool Equals(object obj)
{
var newObj = obj as MyClass;
if (null != newObj)
{
return this.GetHashCode() == newObj.GetHashCode();
}
else
{
return base.Equals(obj);
}
}
// Since this is an entity I can use its Id
// When I don't have an Id, I usually make a composite key of the properties
public override int GetHashCode()
{
return String.Format("MyClass{0}", this.Id.ToString()).GetHashCode();
}
Run Code Online (Sandbox Code Playgroud) 测试Equals
方法非常简单(据我所知).但是你怎么测试这个GetHashCode
方法呢?
如您所知,GetHashCode返回一个半唯一值,可用于标识集合中的对象实例.作为一种好的做法,建议覆盖此方法并实现自己的方法.
我的问题是 - 在处理自定义对象时是否覆盖此方法?如果是这样,您使用什么算法来生成唯一ID?
我正在考虑生成GUID,然后从该识别器获取整数数据.
EnumerableObject : IEnumerable<Foo>
包裹一个 List<Foo>
如果EnumerableObject a.SequenceEquals( EnumerableObject b)
,那么他们是平等的.
因此,GetHashCode
必须实施.问题是XORing列表中的每个元素将返回任何列表的相同哈希码,所有列表都包含所有且只有相同的元素,而不管顺序如何.就工作而言,这是好的,但会导致许多冲突,这将减慢检索速度等.
GetHashCode
对于依赖于顺序的对象列表,什么是一种好的,快速的方法?
我有一个枚举
public enum INFLOW_SEARCH_ON
{
ON_ENTITY_HANDLE = 0,
ON_LABEL = 1,
ON_NODE_HANDLE = 2
} // enum INFLOW_SEARCH_ON
Run Code Online (Sandbox Code Playgroud)
我必须使用这个枚举来在网格列中进行搜索
获取我正在使用的列索引
MyEnumVariable.GetHashCode()
Run Code Online (Sandbox Code Playgroud)
哪个工作正常,或者我应该使用
(short)MyEnumVariable
Run Code Online (Sandbox Code Playgroud)
我对使用GetHashCode()感到困惑.使用它有什么问题吗?
所以我试图弄清楚如何GetHashCode()
在VB中正确覆盖大量的自定义对象.一些搜索引导我得到这个美妙的答案.
除了有一个问题:VB缺少.NET 4.0中的checked
和unchecked
关键字.据我所知,无论如何.因此,使用乔恩斯基特的实现,我想对具有三个主要成员一个相当简单的类创建这样一个覆盖:Name As String
,Value As Int32
,和[Type] As System.Type
.因此,我提出:
Public Overrides Function GetHashCode() As Int32
Dim hash As Int32 = 17
hash = hash * 23 + _Name.GetHashCode()
hash = hash * 23 + _Value
hash = hash * 23 + _Type.GetHashCode()
Return hash
End Function
Run Code Online (Sandbox Code Playgroud)
问题:即使像这样的简单对象,Int32也太小了.我测试的特定实例将"Name"作为一个简单的5个字符的字符串,并且该哈希值足够接近Int32的上限,当它试图计算哈希值(Value)的第二个字段时,它会溢出.因为我找不到粒度checked
/ unchecked
支持的VB等价物,所以我无法解决这个问题.
我也不想删除整个项目中的Integer溢出检查.这个东西可能...... 40%完成(我做了,TBH),我有更多的代码要写,所以我需要这些溢出检查很长一段时间.
GetHashCode
对于VB和Int32 ,Jon的版本的"安全"版本是什么?或者,.NET 4.0 在某个地方有checked
/ unchecked
我在MSDN上很难找到吗?
编辑:
根据链接的SO问题,最底层的一个不受欢迎的答案提供了一个 …
从 ValueType.cs
**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.
今天当我使用KeyValuePair作为字典中的键(它存储了xml属性名称(枚举)和它的值(字符串))时,我被它咬了,并期望它根据其所有字段计算它的哈希码,但根据实施情况,它只考虑了关键部分.
示例(来自Linqpad的c/p):
void Main()
{
var kvp1 = …
Run Code Online (Sandbox Code Playgroud) 考虑到identity属性可以为null,以下哪项是正确/更好的.
public override int GetHashCode()
{
if (ID == null) {
return base.GetHashCode();
}
return ID.GetHashCode();
}
Run Code Online (Sandbox Code Playgroud)
要么
public override int GetHashCode()
{
if (ID != null) {
return ID.GetHashCode();
}
return 0;
}
Run Code Online (Sandbox Code Playgroud)
更新1:更新了第二个选项.
更新2:以下是Equals实现:
public bool Equals(IContract other)
{
if (other == null)
return false;
if (this.ID.Equals(other.ID)) {
return true;
}
return false;
}
public override bool Equals(object obj)
{
if (obj == null)
return base.Equals(obj);
if (!obj is IContract) {
throw new InvalidCastException("The 'obj' argument is not …
Run Code Online (Sandbox Code Playgroud) gethashcode ×10
c# ×8
hashcode ×3
.net ×2
algorithm ×2
enums ×1
equals ×1
iequatable ×1
immutability ×1
methods ×1
overriding ×1
string ×1
tdd ×1
unit-testing ×1
vb.net ×1