.Net中自定义类作为Dictionary的key详解
来源:互联网 发布:java方法重写快捷键 编辑:程序博客网 时间:2024/06/14 01:35
在定义数据结构时,Dictionary提供了快速查找数据的功能,另外Dictionary< TKey, TValue >属于key-value键值对数据结构,提供了泛型的灵活性,是数据结构的一个利器,但是目前拥有的string,int,bool等基础数据类型并不能满足我们的需求,那么如何把自定义的数据类作为Dictionary的key呢?
本文对Dict的内部实现会有提出,但不详细讨论,以解决标题问题为主,如果有想详细了解Dictionary内部实现等更多细节,请转到官网:
https://msdn.microsoft.com/en-us/library/xfhwa508(v=vs.110).aspx
首先需要搞清楚以下问题
- Dictionary是如何通过key找到的value?
- 需要怎么做才可以让Dictionary认同我们的自定义类作为Key?
- 具体代码应该怎么写,去实现?
一、Dictionary是如何通过key找到的value?
首先提几个简单的概念,对我们理解Dictionary有很大的帮助。
哈希表
定义:是一种用于描述有联系键值对数据结构的表。
.NET中有Hashtable的类型,它是一个通过关键字直接访问内存存储位置的数据结构。Dict使用了它,也就是说,Dictionary内部的key,value的存放与查找其实都是由固定的内存地址的,但是数据量多了难免会出现多个key或者value拥有同样的内存地址,这样我们再通过寻址操作数据时就会出现冲突的问题,这个我们叫碰撞冲突。
Dict解决碰撞冲突的方案
Dict采用分离链接法,什么意思呢?就是当不同value被分配到同一个地址时,Dict会在那个地址下再建一个链接,用于存放不同value,放张图大家应该就知道是怎么回事了。
明白了以上两个概念,我们基本上就可以理解这句话了:
Dict判断查找key时,首先会调用GetHashCode方法,来取得key的Hashtable,判断Hashtable是否一致,如果Hashtable一样还不算找到,还需要继续判断存放的value是不是(相等)Equal,两个条件都满足,才算真正找到了我们需要的key,然后取出Dictionary存放的value值。
二、需要怎么做才可以让Dictionary认同我们的自定义类作为Key?
举一个栗子:
using System.Collections.Generic;using System.Linq;using System.Text;using System.Threading.Tasks;namespace test_Dict{ class Program { class MyClass { private int ID { get; set; } private string name { get; set; } public MyClass(int ID, string name) { this.ID = ID; this.name = name; } } static void Main(string[] args) { MyClass class_one = new MyClass(100,"nini_boom"); MyClass class_two = new MyClass(200,"liyang"); MyClass class_three = new MyClass(100, "nini_boom"); Dictionary<MyClass, int> _TestDict = new Dictionary<MyClass, int>(); _TestDict.Add(class_one,1); _TestDict.Add(class_two,2); Console.WriteLine(_TestDict.ContainsKey(class_three)); Console.ReadKey(); } }}
可以看出,即使我们的class_three和class_one在内容上完全相等,但是Dict中仍然找不到。为什么呢?
因为Dict认为的key相等和我们认为的相等不一样
为什么Dict不认为相等呢?我们知道,.Net中所有的数据结构都是继承了object,但是object本身对继承了它的数据一无所知,所以为了防止继承了objece的数据发生碰撞冲突现象,所以object的做法是让每一个继承它的数据的Hashtable都尽量不一样,因为我们的MyClass也是继承了object的,所以Dict在比较Class_one与class_three 的Hashtable时就认为他俩不相等,所以找不到。
为了实现在内容上相等的类,就可以寻找到同样内容的Key,也就是让自定义类作为Dictionary的key,我们需要重新定义一套比较的规定,来满足我们认为的相等
三、具体代码怎么写,去实现?
在Dict的内部实现中,比较两个key是否相等用到了两个方法:GetHashCode()和Equal(),所以接下来需要在自定义类中重写GetHashCode()和Equal()方法,分别得出Hashtable和比较规则,下次Dict再次比较时就会调用重写的GetHashCode和Equal来进行比较。
再拿上面的栗子举下,增加两个方法:
using System;using System.Collections.Generic;using System.Linq;using System.Text;using System.Threading.Tasks;namespace test_Dict{ class Program { class MyClass { private int ID { get; set; } private string name { get; set; } public MyClass(int ID, string name) { this.ID = ID; this.name = name; } public override bool Equals(object obj) { var your_class = (MyClass)obj; return your_class.ID == this.ID && your_class.name == this.name; } public override int GetHashCode() { int id_hashcode = ID.GetHashCode(); int name_hashcode = name.GetHashCode(); return id_hashcode + name_hashcode; } } static void Main(string[] args) { MyClass class_one = new MyClass(100,"nini_boom"); MyClass class_two = new MyClass(200,"liyang"); MyClass class_three = new MyClass(100, "nini_boom"); Dictionary<MyClass, int> _TestDict = new Dictionary<MyClass, int>(); _TestDict.Add(class_one,1); _TestDict.Add(class_two,2); Console.WriteLine(_TestDict.ContainsKey(class_three)); Console.ReadKey(); } }}
这次返回的就是True了。
一次解决一个问题并不足够,所以需要从原理考虑,最好一次解决一类问题,这就是技术成长最快的方法,本次举的例子比较简单,如果需要了解稍微复杂一点的自定义类的应用,这里有源码可供下载:
http://download.csdn.net/download/nini_boom/10146964
以及相关介绍,都是本人在实际项目中设计并使用的,对设计框架或设计底层API的朋友会有不错的帮助:
http://blog.csdn.net/nini_boom/article/details/78722940
- .Net中自定义类作为Dictionary的key详解
- 【术】c#字典Dictionary自定义类作为key键
- 知识点总结: c#,使用自定义类型来作为Dictionary的Key
- Java 自定义类作为HashMap的key
- map中使用自定义类指针作为key
- map中使用自定义类指针作为key
- Struct vs Class 作为HashTable或者Dictionary的Key
- Java用自定义的类作为HashMap的key值
- python--用户自定义类对象作为dict的key
- 自定义枚举类 Enum 是否可以作为 HashMap 的key
- .net 中Dictionary的遍历
- java HashMap用自定义类作为key
- java HashMap用自定义类作为key
- Java中Set转List 和 TreeMap中实现自定义类作为key值
- 用自定义类实现vbs中Dictionary的功能
- C#中Dictionary<Key,Value>中[]操作的效率问题
- C# Dictionary中做Key的类应该注意重写getHashCode和Equals
- C# Dictionary中做Key的类应该注意重写getHashCode和Equals
- TypeScript中的 ?: 是什么意思
- Android蓝牙开发【八】hfp接听、挂断电话
- 表现与数据分离第一篇:mvc设计模式实现pdf数据流弹窗预览
- Altium designer 快捷键
- 【三】Springboot+Redis实现密码次数限制
- .Net中自定义类作为Dictionary的key详解
- OpenStack O版 neutron-openvswitch-agent 的一个bug
- Day10—继承、访问控制符、final关键字、对象创建过程、多态、抽象类
- Flume_Sink
- 从四大云计算公司走向 看云行业趋势
- rsync通过服务同步、linux系统日志和screen工具
- centos7下配置golang1.9.2环境
- Android studio进阶之多语言/图片--国际化
- CSS background-size属性