考虑以下对象:
class Route
{
public int Origin { get; set; }
public int Destination { get; set; }
}
Run Code Online (Sandbox Code Playgroud)
Route实现了相等运算符.
class Routing
{
public List<Route> Paths { get; set; }
}
Run Code Online (Sandbox Code Playgroud)
我使用下面的代码为Routing对象实现GetHashCode方法,它似乎工作,但我想知道这是否是正确的方法呢?我依靠平等检查,因为我不确定我以为我会问你们.我可以只是总结哈希码还是我需要做更多的魔术以保证所需的效果?
public override int GetHashCode() =>
{
return (Paths != null
? (Paths.Select(p => p.GetHashCode())
.Sum())
: 0);
}
Run Code Online (Sandbox Code Playgroud)
我GetHashCode()在这里检查了几个问题,以及MSDN和Eric Lippert关于这个主题的文章,但是找不到我想要的东西.
在本文中,Jon Skeet提到他通常使用这种算法来覆盖GetHashCode().
public override int GetHashCode()
{
unchecked // Overflow is fine, just wrap
{
int hash = 17;
// Suitable nullity checks etc, of course :)
hash = hash * 23 + Id.GetHashCode();
return hash;
}
}
Run Code Online (Sandbox Code Playgroud)
现在,我尝试使用它,但Resharper告诉我,方法GetHashCode()应该只使用只读字段进行散列(尽管编译很好).什么是好的做法,因为现在我真的不能让我的字段是只读的?
我尝试通过Resharper生成这个方法,这是结果.
public override int GetHashCode()
{
return base.GetHashCode();
}
Run Code Online (Sandbox Code Playgroud)
这没什么贡献,说实话......
我的问题可能会重复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) 我如何处理GetHashCode函数中的空字段?
Module Module1
Sub Main()
Dim c As New Contact
Dim hash = c.GetHashCode
End Sub
Public Class Contact : Implements IEquatable(Of Contact)
Public Name As String
Public Address As String
Public Overloads Function Equals(ByVal other As Contact) As Boolean _
Implements System.IEquatable(Of Contact).Equals
Return Name = other.Name AndAlso Address = other.Address
End Function
Public Overrides Function Equals(ByVal obj As Object) As Boolean
If ReferenceEquals(Me, obj) Then Return True
If TypeOf obj Is Contact Then
Return Equals(DirectCast(obj, Contact)) …Run Code Online (Sandbox Code Playgroud) 为什么GetHashCode()为同一个字符串返回不同的值?我无法描述如何复制这个,但相信这不是一个恶作剧,以下两行来自我的观察窗口,分别是两次:
"DDD.Events.Application.ApplicationReferenceCreated".GetHashCode() -1386151123 int
"DDD.Events.Application.ApplicationReferenceCreated".GetHashCode() 1858139950 int
Run Code Online (Sandbox Code Playgroud)
怎么会发生这种情况?
我不知道这是否有帮助,但我在VS 2010中运行.NET 4.0并且我正在调试NServiceBus应用程序.
更新:
如果你想知道我最后做了什么,看看这个线程:你能在x64模式下运行时生成x86哈希值吗?
当我使用字典有时我必须更改默认的等于意思,以便比较键.我看到如果我在键的类上重写Equals和GetHashCode,或者我创建了一个实现IEqualityComparer的新类,我有相同的结果.那么使用IEqualityComparer和Equals/GethashCode Override有什么区别?两个例子:
class Customer
{
public string name;
public int age;
public Customer(string n, int a)
{
this.age = a;
this.name = n;
}
public override bool Equals(object obj)
{
Customer c = (Customer)obj;
return this.name == c.name && this.age == c.age;
}
public override int GetHashCode()
{
return (this.name + ";" + this.age).GetHashCode();
}
}
class Program
{
static void Main(string[] args)
{
Customer c1 = new Customer("MArk", 21);
Customer c2 = new Customer("MArk", 21);
Dictionary<Customer, string> d = …Run Code Online (Sandbox Code Playgroud) 我在StackOverflow上阅读了大部分关于的问题GetHashCode.但我仍然不确定是否必须覆盖GetHashCode引用类型.我从另一个问题的某些人那里得到了以下答案:
Object.GetHashCode()使用System.Object类中的内部字段来生成哈希值.创建时,为每个创建的对象分配一个唯一的对象键,存储为整数.这些键从1开始,每次创建任何类型的新对象时都会递增.
如果在.NET Framework 3.5中仍然如此(有人可以确认吗?),那么我在参考类型的默认实现中看到的唯一问题是哈希代码的分布很差.
我会打破我的问题:
a)所以建议覆盖GetHashCode它是否在a中使用Dictionary或者默认实现是否正常?
b)我有很容易做的引用类型,因为它们具有唯一标识它们的字段,但是那些所有成员也是引用类型的引用类型呢.我该怎么办?
我有一个对象,我想生成一个唯一的哈希(覆盖GetHashCode()),但我想避免溢出或不可预测的事情.
代码应该是组合一小组字符串的哈希码的结果.
哈希码将是生成缓存密钥的一部分,因此理想情况下它们应该是唯一的,但是被散列的可能值的数量很小所以我认为概率对我有利.
这样的事情是否足够并且有更好的方法吗?
int hash = 0;
foreach(string item in collection){
hash += (item.GetHashCode() / collection.Count)
}
return hash;
Run Code Online (Sandbox Code Playgroud)
编辑:感谢您的答案到目前为止.@Jon Skeet:不,订单并不重要
我想这几乎是另一个问题,但由于我使用结果生成缓存键(字符串)是否有意义使用像MD5这样的加密哈希函数或只使用此int的字符串表示?
我正在将一些东西从Java移植到C#.在Java中hashcode,a ArrayList取决于其中的项目.在C#中,我总是从List... 获得相同的哈希码
为什么是这样?
对于我的一些对象,哈希码需要不同,因为列表属性中的对象使对象不相等.我希望哈希码对于对象的状态始终是唯一的,并且当对象相等时仅等于另一个哈希码.我错了吗?
我需要一个C#Random类实例的种子,我读到大多数人使用当前时间的滴答计数器.但这是一个64位值,种子需要是32位值.现在我认为GetHashCode()返回a 的方法int应该为其对象提供合理分布的值,这可以用于避免仅使用滴答计数的低32位.但是,我找不到任何有关Int64数据类型的GetHashCode()的信息.
所以,我知道它并不重要,但是下面的工作会像我想的那样好(我不能试错法随机性),或者它可能与使用(int)DateTime.Now.Ticks种子一样工作吗?或者甚至可能更糟糕?谁可以对此有所了解.
int seed = unchecked(DateTime.Now.Ticks.GetHashCode());
Random r = new Random(seed);
Run Code Online (Sandbox Code Playgroud)
编辑:为什么我需要种子而不只是让Random()构造函数完成工作?我需要将种子发送给使用相同种子的其他客户端进行相同的随机序列.
gethashcode ×10
c# ×9
.net ×2
equality ×2
hash ×2
hashcode ×2
.net-4.0 ×1
collections ×1
dictionary ×1
equals ×1
iequatable ×1
java ×1
null ×1
random ×1
resharper ×1
string ×1