有没有办法获取实例的唯一标识符?
GetHashCode()对于指向同一实例的两个引用是相同的.但是,两个不同的实例可以(很容易)获得相同的哈希码:
Hashtable hashCodesSeen = new Hashtable();
LinkedList<object> l = new LinkedList<object>();
int n = 0;
while (true)
{
object o = new object();
// Remember objects so that they don't get collected.
// This does not make any difference though :(
l.AddFirst(o);
int hashCode = o.GetHashCode();
n++;
if (hashCodesSeen.ContainsKey(hashCode))
{
// Same hashCode seen twice for DIFFERENT objects (n is as low as 5322).
Console.WriteLine("Hashcode seen twice: " + n + " (" + hashCode + ")");
break; …Run Code Online (Sandbox Code Playgroud) 我想听听社区关于如何为我的对象实现GetHashCode(或覆盖它)的消息.我理解如果我覆盖equals方法,我需要这样做.我已经实现了相当多的次数,有时只是调用基本方法.我知道如果对象包含相同的细节(成员),我的对象应该等于对象的另一个实例.从班级成员那里获取哈希码的最佳方法是什么?
GetHashCode()在byte[]数组上调用时计算什么?具有相同内容的2个数据阵列不提供相同的散列.
我经常听说这些方法(Object.hashCode和System.identityHashCode)返回对象的地址,或者从地址快速计算的东西; 但我也很确定垃圾收集器会移动并压缩物体.由于哈希码不能改变,这就出现了问题.我知道这不是人们日常工作需要知道的事情,但我想了解内部情况.那么,有谁知道这是如何在Java中实现的?或.NET,因为它们可能类似.
class A
{
public override int GetHashCode()
{
return 1;
}
}
class B : A
{
public override int GetHashCode()
{
return ((object)this).GetHashCode();
}
}
new B().GetHashCode()
Run Code Online (Sandbox Code Playgroud)
这会溢出堆栈.我怎么能叫Object.GetHashCode()的B.GetHashCode()?
编辑:B现在继承自A.
我的问题可能会重复Object.GetHashCode()的默认实现,但我再问一次,因为我不理解那个问题的接受答案.
首先,我对上一个问题的接受答案有三个问题,引用了一些文档如下:
"但是,因为在垃圾回收期间回收对象后可以重用此索引,所以可以为两个不同的对象获取相同的哈希码."
这是真的?在我看来,两个对象将不会具有相同的哈希码,因为在对象被垃圾收集(即不再存在)之前,对象的代码不会被重用.
"另外,表示相同值的两个对象只有在完全相同的对象时才具有相同的哈希码."
这是一个问题吗?例如,我想将一些数据与DOM树中的每个节点实例相关联.为此,"节点"必须具有标识或哈希码,以便我可以将它们用作数据字典中的键.是不是一个哈希码来识别它是否是"完全相同的对象",即"引用相等而不是"值相等",我想要什么?
"这个实现对于散列并不是特别有用;因此,派生类应该覆盖GetHashCode"
这是真的?如果它对散列不好,那么如果它有什么好处,为什么它甚至被定义为Object的方法呢?
我的最终(也许对我来说最重要的)问题是,如果我必须发明/覆盖具有"引用相等"语义的任意类型的GetHashCode()实现,则以下是一个合理且良好的实现:
class SomeType
{
//create a new value for each instance
static int s_allocated = 0;
//value associated with this instance
int m_allocated;
//more instance data
... plus other data members ...
//constructor
SomeType()
{
allocated = ++s_allocated;
}
//override GetHashCode
public override int GetHashCode()
{
return m_allocated;
}
}
Run Code Online (Sandbox Code Playgroud)
编辑
仅供参考我使用以下代码测试它:
class TestGetHash
{
//default implementation
class First
{
int m_x;
}
//my implementation
class …Run Code Online (Sandbox Code Playgroud) 我在StackOverflow上阅读了大部分关于的问题GetHashCode.但我仍然不确定是否必须覆盖GetHashCode引用类型.我从另一个问题的某些人那里得到了以下答案:
Object.GetHashCode()使用System.Object类中的内部字段来生成哈希值.创建时,为每个创建的对象分配一个唯一的对象键,存储为整数.这些键从1开始,每次创建任何类型的新对象时都会递增.
如果在.NET Framework 3.5中仍然如此(有人可以确认吗?),那么我在参考类型的默认实现中看到的唯一问题是哈希代码的分布很差.
我会打破我的问题:
a)所以建议覆盖GetHashCode它是否在a中使用Dictionary或者默认实现是否正常?
b)我有很容易做的引用类型,因为它们具有唯一标识它们的字段,但是那些所有成员也是引用类型的引用类型呢.我该怎么办?
我遇到了一个断言HashSet <T> .Contains()是一个O(1)操作.这令我感到惊讶,因为我遇到的每次哈希讨论都提到了碰撞的可能性,可能导致O(n)运行时间.
好奇,我查看了HashSet <T> .Contains和HashTable.Contains的文档.两种方法的文档都提出了同样的主张.
当我查看反射器时,HashSet <T> .Contains()是用for循环实现的,它通过一个包含具有相同散列值的槽列表.
现在可以肯定的是,那些关于哈希的讨论也提到了一个好的哈希算法可以避免冲突,在这种情况下查找确实是O(1).但我对Big O符号的理解是,它是最糟糕的运行时间,而不是最好的.
O(1)声明是否错误?或者我错过了什么?
我正在阅读有效的C#并且有一条关于Object.GetHashCode()我不明白的评论:
Object.GetHashCode()使用类中的内部字段System.Object来生成哈希值.创建时,为每个创建的对象分配一个唯一的对象键,存储为整数.
这些键从1开始,每次创建任何类型的新对象时都会递增.对象标识字段在System.Object构造函数中设置,以后不能修改.Object.GetHashCode()将此值作为给定对象的哈希码返回.
我试着查看文档,Object.GetHashCode()但没有找到任何相关信息.
我编写了一段简单的代码来打印新生成的对象的哈希码:
using System;
namespace TestGetHashCode
{
class Program
{
static void Main(string[] args)
{
for (int i = 0; i < 100; i++)
{
object o = new object();
Console.WriteLine(o.GetHashCode());
}
}
}
}
Run Code Online (Sandbox Code Playgroud)
打印的前几个数字是:
37121646,
45592480,
57352375,
2637164,
41014879,
3888474,
25209742,
26966483,
31884011
Run Code Online (Sandbox Code Playgroud)
哪个似乎不合适
这些键从1开始,每次创建任何类型的新对象时都会递增...
Object.GetHashCode()返回此值
然后,为了找到这个"内部字段System.Object"我尝试使用ReSharper反编译源,但我找到的代码是
[TargetedPatchingOptOut("Performance critical to inline across NGen image boundaries")]
[__DynamicallyInvokable]
public …Run Code Online (Sandbox Code Playgroud) 在VB.NET中,我必须比较一个select case语句中的一些对象.
由于默认情况下select case使用=operator而没有为对象定义,因此抛出了编译错误.
我目前使用此解决方法:
Select Case True
Case sender Is StyleBoldButton
Case sender Is StyleUnderButton
Case sender Is StyleItalicButton
End Select
Run Code Online (Sandbox Code Playgroud)
这实际上有效.
是否有更漂亮的东西可以看到,更容易理解?
c# ×8
.net ×4
gethashcode ×4
hash ×3
hashcode ×2
case ×1
dictionary ×1
equals ×1
inheritance ×1
internals ×1
java ×1
object ×1
select ×1
unique ×1
vb.net ×1