Tag: gethashcode

当对象的标识符为空时,GetHashCode应该返回什么?

考虑到identity属性可以为null,以下哪项是正确/更好的。 public override int GetHashCode() { if (ID == null) { return base.GetHashCode(); } return ID.GetHashCode(); } 要么 public override int GetHashCode() { if (ID != null) { return ID.GetHashCode(); } return 0; } 更新1:更新了第二个选项。 更新2:以下是Equals实现: public bool Equals(IContract other) { if (other == null) return false; if (this.ID.Equals(other.ID)) { return true; } return false; […]

Equals,GetHashCode,EqualityComparers和模糊平等

对于具有属性A,B,C,D,StartDate和EndDate的对象,如果我想实现任何两个对象相等的东西,如果它们具有相同的A,B和C以及重叠的日期范围,那将如何完成? 我试过像这样创建一个EqualityComparer public override bool Equals(RateItem x, RateItem y) { bool equal = true; if ((xA != yA || xB != yB || xC != yC || (x.StartDate < y.StartDate && x.EndDate y.StartDate && y.EndDate <= x.StartDate))) { equal = false; } return equal; } 但似乎框架中的很多地方都忽略了Equals并使用了GetHashCode,文档根本就不清楚。 当我去实现GetHashCode时,我不知道如何在不忽略日期的情况下使HashCodes变得相同。 为了使其更具体,这与项目管理和费率有关。 我想实现一个业务规则,即同一个角色中同一个项目中的同一个人在同一时间段内不能有不同的费率。 因此Bob在Project DeathMarch中担任DBA角色,在任何给定时间只能有一个有效的账单费率来记录他的时间。 如果他需要在同一时间段内以不同的速率记录QA分析师的角色,那就没问题。 这是一个庞大的预先存在的系统,因此更改域对象结构不是一种选择。

逆向工程String.GetHashCode

String.GetHashCode的行为取决于程序架构。 因此它将在x86中返回一个值,在x64上返回一个值。 我有一个必须在x86中运行的测试应用程序,它必须预测必须在x64上运行的应用程序的哈希码输出。 下面是mscorwks中String.GetHashCode实现的反汇编。 public override unsafe int GetHashCode() { fixed (char* text1 = ((char*) this)) { char* chPtr1 = text1; int num1 = 0x15051505; int num2 = num1; int* numPtr1 = (int*) chPtr1; for (int num3 = this.Length; num3 > 0; num3 -= 4) { num1 = (((num1 <≫ 0x1b)) ^ numPtr1[0]; if (num3 […]

我是否需要在引用类型上覆盖GetHashCode()?

我在StackOverflow上阅读了关于GetHashCode大多数问题。 但我仍然不确定是否必须在引用类型上覆盖GetHashCode 。 我从另一个问题的某些人那里得到了以下答案: Object.GetHashCode()使用System.Object类中的内部字段来生成哈希值。 创建时,为每个创建的对象分配一个唯一的对象键,存储为整数。 这些键从1开始,每次创建任何类型的新对象时都会递增。 如果在.NET Framework 3.5中仍然如此(有人可以确认吗?),那么我在参考类型的默认实现中看到的唯一问题是哈希代码的分布很差。 我会打破我的问题: a)所以它建议覆盖GetHashCode ,如果它在Dictionary或者默认实现是否正常? b)我有很容易做的引用类型,因为它们有唯一标识它们的字段但是那些所有成员也是引用类型的引用类型。 我该怎么办?

具有列表对象的类的GetHashCode

我有这样一堂课: public class Cycle { public List Edges { get; private set; } public override bool Equals(object obj) { Cycle cycle = (Cycle)obj; var list1 = cycle.Edges; var list2 = Edges; var same = list1.Except(list2).Count() == 0 && list2.Except(list1).Count() == 0; return same; } public override int GetHashCode() { // return Edges.GetHashCode(); } } 如您所见,如果两个Edge列表相同,那么我认为Cycles是相同的。 […]

通用IEqualityComparer 和GetHashCode

对于实现大量的IEqualityComparers有些懒惰,并且考虑到我无法轻松编辑被比较对象的类实现,我使用了以下内容,意在与Distinct()和Except()扩展方法一起使用。 : public class GenericEqualityComparer : IEqualityComparer { Func compareFunction; Func hashFunction; public GenericEqualityComparer(Func compareFunction, Func hashFunction) { this.compareFunction = compareFunction; this.hashFunction = hashFunction; } public bool Equals(T x, T y) { return compareFunction(x, y); } public int GetHashCode(T obj) { return hashFunction(obj); } } 看起来很不错,但每次真的需要一个哈希函数吗? 我知道哈希码用于将对象放入存储桶中。 不同的桶,对象不相等,并且不调用相等。 如果GetHashCode返回相同的值,则调用equals。 (来自: 为什么在重写Equals方法时重写GetHashCode很重要? ) 所以可能出现问题,例如(我听到很多程序员惊恐地尖叫),GetHashCode返回一个常量,强制调用Equal?

在没有不可变字段的类中重写Object.GetHashCode()时要返回什么?

好吧,在你因为互联网上发布了数百个类似的声音问题而疯狂之前,我可以向你保证,我刚刚花了最后几个小时阅读所有这些问题并且没有找到我的问题的答案。 背景: 基本上,我的一个大型应用程序遇到了ListBox.SelectedItem属性上的某些Binding将停止工作或者在对当前所选项目进行编辑后程序崩溃的情况。 我最初问过“已经添加了相同密钥的项目”这里从代码问题中选择ListBoxItem的例外 ,但没有得到答案。 直到本周,我才有时间解决这个问题。 现在简而言之,我找到了问题的原因。 这是因为我的数据类型类已经覆盖了Equals方法,因此也覆盖了GetHashCode方法。 现在对于那些不知道这个问题的人,我发现你只能使用不可变字段/属性来实现GetHashCode方法。 使用Harvey Kwok对Overriding GetHashCode()post的回答来解释这个: 问题是Dictionary和HashSet集合正在使用GetHashCode将每个项目放在存储桶中。 如果基于某些可变字段计算哈希码,并且在将对象放入HashSet或Dictionary后实际更改了字段,则无法再从HashSet或Dictionary中找到该对象。 所以实际问题是因为我在GetHashCode方法中使用了可变属性。 当用户在UI中更改了这些属性值时,对象的关联哈希码值发生了更改,然后在其集合中找不到项。 题: 所以,我的问题是处理我需要在没有不可变字段的类中实现GetHashCode方法的情况的最佳方法是什么? 对不起,让我更具体一点,因为之前已经提出了这个问题。 Overriding GetHashCode()post中的答案表明,在这些情况下,最好只返回一个常量值……有些建议返回值1 ,而其他建议返回素数。 就个人而言,我看不出这些建议之间有什么区别,因为我原本以为只会有一个桶用于其中任何一个。 此外,Eric Lippert博客中关于GetHashCode的指南和规则有一个标题为指南的部分:哈希码的分布必须是“随机的” ,这突出了使用导致使用不足的桶的算法的缺陷。 他警告说,算法会减少使用的桶数,并在桶变得非常大时导致性能问题 。 当然,返回常数属于这一类。 我想到了为我的所有数据类型类(仅在C#中,而不是数据库中)添加一个额外的Guid字段,特别是在GetHashCode方法中使用。 所以我想在这个长篇介绍的最​​后,我的实际问题是哪个实现更好? 总结一下: 摘要: 在没有不可变字段的类中重写Object.GetHashCode()时,最好从GetHashCode方法返回一个常量,还是为每个类创建一个额外的readonly字段,仅用于GetHashCode方法? 如果我应该添加一个新字段,它应该是什么类型,我不应该将它包含在Equals方法中? 虽然我很高兴收到任何人的答复,但我真的希望得到高级开发人员的答案,他们对这个主题有充分的了解。

Object.GetHashCode

我的问题可能会重复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 […]

GetHashCode扩展方法

在阅读StackOverflow上关于重写GetHashCode()所有问题和答案之后,我编写了以下扩展方法,以便轻松方便地覆盖GetHashCode() : public static class ObjectExtensions { private const int _seedPrimeNumber = 691; private const int _fieldPrimeNumber = 397; public static int GetHashCodeFromFields(this object obj, params object[] fields) { unchecked { //unchecked to prevent throwing overflow exception int hashCode = _seedPrimeNumber; for (int i = 0; i < fields.Length; i++) if (fields[i] != null) hashCode […]

如何在匿名类型上实现Equals和GetHashCode?

帮助说: 匿名类型是直接从对象派生的类类型,不能转换为除object之外的任何类型。 编译器为每个匿名类型提供名称,尽管您的应用程序无法访问它。 从公共语言运行库的角度来看,匿名类型与任何其他引用类型没有区别。 如果程序集中的两个或多个匿名对象初始值设定项指定了具有相同顺序且具有相同名称和类型的属性序列,则编译器会将对象视为相同类型的实例。 它们共享相同的编译器生成的类型信息。 因为匿名类型上的Equals和GetHashCode方法是根据属性的Equals和GetHashCode方法定义的,所以同一匿名类型的两个实例只有在它们的所有属性相等时才相等。 这些都是真的,但是怎么样? 参考源明确地显示了如何比较对象( ReferenceEquals )和“直接从对象派生”的类型不能具有这种特殊行为。 它与ValueType的Equals行为也不匹配。 那怎么办? 匿名类型如何覆盖Equals()和GetHashCode()而没有任何可见的覆盖?