当将对象添加到.NET System.Collections.Generic.Dictionary类中时,密钥的哈希码将内部存储并用于后续比较.当哈希码在其初始插入到字典之后变化时,它通常变得“不可访问”,并且当存在检查(即使使用相同的引用)返回false(下面的示例代码)时,也可能使用户感到惊讶.

GetHashCode文档说:

The GetHashCode method for an object must consistently return the same hash code as long as there is no modification to the object state that determines the return value of the object’s Equals method.

因此,根据GetHashCode文档,当equality确定状态改变时,哈希码可能会更改,但Dictionary实现不支持此操作.

当前的.NET字典实现是否被破坏,因为它错误地忽略了哈希码容限? GetHashCode()只能基于不可变成员?还有还有什么可以打破可能的假二分法?

class Hashable
{
    public int PK { get; set; }

    public override int GetHashCode()
    {
        if (PK != 0) return PK.GetHashCode();
        return base.GetHashCode();
    }

    public override bool Equals(object obj)
    {
        return Equals(obj as Hashable);
    }

    public virtual bool Equals(Hashable other)
    {
        if (other == null) return false;
        else if (ReferenceEquals(this,other)) return true;
        else if (PK != 0 && other.PK != 0) return Equals(PK,other.PK);
        return false;
    }

    public override string ToString()
    {
        return string.Format("Hashable {0}",PK);
    }
}

class Test
{
    static void Main(string[] args)
    {
        var dict = new Dictionary<Hashable,bool>();
        var h = new Hashable();
        dict.Add(h,true);

        h.PK = 42;
        if (!dict.ContainsKey(h)) // returns false,despite same reference
            dict.Add(h,false);
    }
}

解决方法

不,在插入字典之后,你不应该将键(以实质的方式)变异.这是通过设计,以及我使用过的每个散列表的工作原理.文档甚至指定:

As long as an object is used as a key in the Dictionary<TKey,TValue>,it must not change in any way that affects its hash value. Every key in a Dictionary<TKey,TValue> must be unique according to the dictionary’s equality comparer. A key cannot be null,but a value can be,if the value type TValue is a reference type.

所以只会让用户看不到文档的惊喜:)

c# – 是字典破碎还是应该GetHashCode()只能基于不可变的成员?的更多相关文章

  1. 《Swift NSDictionary 的详细使用和部分方法介绍 和 哈希表散列)的阐述和解释 》

    /*《SwiftNSDictionary的详细使用和部分方法介绍和哈希表(散列)的阐述和解释》*//*第一步:我们首先,必须了解一个概念性的东西那就是:哈希哈希的主要解释是:哈希算法将任意长度的二进制值映射为较短的固定长度的二进制值,这个小的二进制值称为哈希值。2》哈希列表是跟进式变化的。作为线性数据结构与表格和队列等相比,哈希表无疑是查找速度比较快的一种。在哈希方法中使用的转换函数hash被称作哈希函数。按照此中算法构造出来的表叫做哈希表。

  2. Swift 中“等同性”、“比较”、“哈希” 概念理解

    甚至某些场景下还需要将其作为键值对中的Key,这就涉及到哈希函数以及哈希值的碰撞问题了。不过仔细查看代码,我们会发现上诉冲突的原因之一就是name、capital属性采用了同样的哈希函数。并修改Country中的哈希实现:改进后上诉冲突得以解决:总结本文简单的介绍了Swift中“等同性”、“比较”、“哈希”的概念,并对一些常见哈希冲突进行了分析。

  3. Dictionary如何在Swift中使用Equatable协议?

    focusedCommentId=19980&page=com.atlassian.jira.plugin.system.issuetabpanels:comment-tabpanel#comment-19980What’sactuallyhappening:Wehashavalueonlyonceoninsertion.Wedon’tusehashesforcomparisonofelements,only==.Usinghashesforcomparisonisonlyreasonableifyous

  4. Java超详细分析讲解哈希表

    哈希表是一种根据关键码去寻找值的数据映射结构,该结构通过把关键码映射的位置去寻找存放值的地方,说起来可能感觉有点复杂,我想我举个例子你就会明白了,最典型的的例子就是字典

  5. PHP哈希表实现算法原理解析

    这篇文章主要介绍了PHP哈希表实现算法原理解析,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下

  6. 详解JavaScript实现哈希表

    哈希表是一种非常重要的数据结构,几乎所有的编程语言都有直接或者间接的应用这种数据结构。本文将为大家介绍通过JavaScript如何实现哈希表,以及哈希表的一些常用操作,需要的可以参考一下

  7. 一文详解Python中哈希表的使用

    哈希表或称为散列表,是一种常见的、使用频率非常高的数据存储方案。本文将站在开发者的角度,带着大家一起探究哈希的世界,感兴趣的小伙伴可以跟随小编一起学习一下

  8. Java真题实练掌握哈希表的使用

    哈希表是一种根据关键码去寻找值的数据映射结构,该结构通过把关键码映射的位置去寻找存放值的地方,说起来可能感觉有点复杂,我想我举个例子你就会明白了,最典型的的例子就是字典

  9. zend-framework – 你如何对包含CSRF表单元素的Zend_Form进行单元测试?

    我正在使用带有Zend_Form的CSRF隐藏哈希元素并尝试单元测试登录但不知道如何编写单元测试以包含该元素.查看文档并阅读尽可能多的教程.我甚至deliciousedthemall,但没有人提到这一点.正确的哈希存储在会话中,Hash表单元素有一个Zend_Session_Namespace实例,该实例包含哈希的命名空间.要对元素进行单元测试,您可以将元素中的Zend_Session_Names

  10. php – DefaultPasswordHasher为相同的值生成不同的哈希值

    我有一个密码存储在数据库哈希与DefaultPasswordHasher添加操作.我有另一个操作来更改登录用户的密码,在此表单上我有一个名为current_password的字段,我需要将其与数据库中的当前密码值进行比较.问题是DefaultPasswordHasher每次为表格的值散列时都会生成不同的哈希值,因此这将永远不会与数据库中的哈希值匹配.按照’current_password’字段的验

随机推荐

  1. c# – (wpf)Application.Current.Resources vs FindResource

    所以,我正在使用C#中的WPF创建一个GUI.它看起来像这样:它现在还没有完成.这两行是我尝试制作一种数据表,它们在XAML中是硬编码的.现在,我正在C#中实现添加新的水果按钮功能.我在XAML中有以下样式来控制行的背景图像应该是什么样子:因此,在代码中,我为每列col0,col1和col2创建一个图像,如果我使用以下代码,它添加了一个如下所示的新行:如你所见,它不太正确……为什么一个似乎忽略了一些属性而另一个没有?

  2. c# – 绑定DataGridTemplateColumn

    似乎我已经打了个墙,试图在DataGrid上使用DataTemplates.我想要做的是使用一个模板来显示每个单元格的两行文本.但是似乎无法以任何方式绑定列.以下代码希望显示我想做的事情.注意每个列的绑定:模板列没有这样的东西,因此,这个xaml不可能工作.我注定要将整个DataTemplate复制到每个列,只是对每个副本都有不同的约束?解决方法我不完全确定你想要做什么,但如果您需要获取整行的DataContext,可以使用RelativeSource绑定来移动视觉树.像这样:

  3. c# – 学习设计模式的资源

    最近我来到了这个设计模式的概念,并对此感到非常热情.你能建议一些帮助我深入设计模式的资源吗?

  4. c# – 是否有支持嵌入HTML页面的跨操作系统GUI框架?

    我想开发一个桌面应用程序来使用跨系统,是否有一个GUI框架,允许我为所有3个平台编写一次代码,并具有完全可脚本化的嵌入式Web组件?我需要它有一个API来在应用程序和网页之间进行交流.我知道C#,JavaScript和一些python.解决方法Qt有这样的事情QWebView.

  5. c# – 通过字符串在对象图中查找属性

    我试图使用任意字符串访问嵌套类结构的各个部分.给出以下(设计的)类:我想要从Person对象的一个实例的“PersonsAddress.HousePhone.Number”获取对象.目前我正在使用反思来做一些简单的递归查找,但是我希望有一些忍者有更好的想法.作为参考,这里是我开发的(crappy)方法:解决方法您可以简单地使用标准的.NETDataBinder.EvalMethod,像这样:

  6. c# – 文件下载后更新页面

    FamilyID=0a391abd-25c1-4fc0-919f-b21f31ab88b7&displaylang=en&pf=true它呈现该页面,然后使用以下元刷新标签来实际向用户提供要下载的文件:你可能需要在你的应用程序中做类似的事情.但是,如果您真的有兴趣在文件完全下载后执行某些操作,那么您的运气不佳,因为没有任何事件可以与浏览器进行通信.执行此操作的唯一方法是上传附件时使用的AJAXupload.

  7. c# – 如何在每个机器应用程序中实现单个实例?

    我必须限制我的.net4WPF应用程序,以便每台机器只能运行一次.请注意,我说每个机器,而不是每个会话.我使用一个简单的互斥体实现单实例应用程序,直到现在,但不幸的是,这样一个互斥是每个会话.有没有办法创建机器互连,还是有其他解决方案来实现每个机器应用程序的单个实例?

  8. c# – WCF和多个主机头

    我的雇主网站有多个主机名,都是同一个服务器,我们只是显示不同的皮肤来进行品牌宣传.不幸的是,在这种情况下,WCF似乎不能很好地工作.我试过overridingthedefaulthostwithacustomhostfactory.这不是一个可以接受的解决方案,因为它需要从所有主机工作,而不仅仅是1.我也看过thisblogpost,但是我无法让它工作,或者不是为了解决我的问题.我得到的错误是“这

  9. c# – ASP.NET MVC模型绑定与表单元素名称中的虚线

    我一直在搜索互联网,试图找到一种方式来容纳我的表单元素的破折号到ASP.NET的控制器在MVC2,3或甚至4中的默认模型绑定行为.作为一名前端开发人员,我更喜欢在我的CSS中使用camelCase或下划线进行破折号.在我的标记中,我想要做的是这样的:在控制器中,我会传入一个C#对象,看起来像这样:有没有办法通过一些正则表达式或其他行为来扩展Controller类来适应这种情况?我讨厌这样的事实,我必须这样做:甚至这个:思考?

  10. c# – 用户界面设计工具

    我正在寻找一个用户界面设计工具来显示文档中可能的GUI.我不能生成代码.我知道MicrosoftVisio提供了一个功能.但有什么办法吗?您使用哪种软件可视化GUI?

返回
顶部