自写一个模仿Dictionary与Foreach的实现及心得总结

所属分类: 网络编程 / ASP.NET 阅读数: 849
收藏 0 赞 0 分享
自己写一个类模仿Dictionary实现
a、自定义字典类MyDic
复制代码 代码如下:

using System.Collections.Generic;
namespace _10_自己写Dictionary {
class KeyValuePair {
public KeyValuePair() {
}
public KeyValuePair(string key, string value) {
this.key = key;
this.value = value;
}
private string key;
public string Key {
get {
return key;
}
set {
key = value;
}
}
private string value;
public string Value {
get {
return this .value;
}
set {
this.value = value ;
}
}
}
class MyDic {
List<KeyValuePair > list = new List<KeyValuePair >();
public void Add(string key, string value) {
list.Add( new KeyValuePair (key, value));
}
public bool ContainsKey(string key) {
bool res = false ;
foreach(KeyValuePair item in list) {
if(item.Key == key) {
res = true;
break;
}
}
return res;
}
}
}

b、调用测试
复制代码 代码如下:

using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Linq;
using System.Text;
namespace _10_自己写Dictionary {
class Program {
static void Main(string[] args) {
//Dictionary方法实现
Dictionary<string , string> dic = new Dictionary <string, string>();
string[] filecon = File .ReadAllLines("英汉词典TXT格式.txt", Encoding.Default);
for(int i = 0; i < filecon.Count(); i++) {
string[] arr = filecon[i].Split(new char[] { ' ' }, StringSplitOptions.RemoveEmptyEntries);
if(!dic.ContainsKey(arr[0])) {
dic.Add(arr[0], arr[1]);
}
}
Stopwatch sw = new Stopwatch();
sw.Start();
dic.ContainsKey( "china");
sw.Stop();
Console.WriteLine(sw.Elapsed);//00:00:00:0000055;
//自己写的list实现
MyDic mydic = new MyDic();
string[] filecon2 = File .ReadAllLines("英汉词典TXT格式.txt", Encoding.Default);
for(int i = 0; i < filecon2.Count(); i++) {
string[] arr = filecon2[i].Split(new char[] { ' ' }, StringSplitOptions.RemoveEmptyEntries);
if(!mydic.ContainsKey(arr[0])) {
mydic.Add(arr[0], arr[1]);
}
}
Stopwatch sw2 = new Stopwatch();
sw2.Start();
mydic.ContainsKey( "china");
sw2.Stop();
Console.WriteLine(sw2.Elapsed);//00:00:00:0001287;慢了多少倍!!! 因为dictionary比list多了字典目录
Console.Read();
}
}
}

b中测试结果显示自己模仿的没有.Net FrameWork提供的快 为什么呢?

答:Dictionary中有一个存储键值对的区域,这个区域的每个存储单元有地址编号,根据hashCode算法,计算key的值的键值对应该存储的地址,将键值对放入指定的地址即可。查找的时候首先计算key的地址,就可以找到数据了。根据key找房间号,而不是逐个房间找。(*)或者说:当把一个kvp,采用一个固定算法(散列算法)根据key来计算这个kvp存放的地址。取的时候也是根据要找的key可以快速算出kvp存放的地址。

面试题中经常会问Foreach实现了什么接口这个问题很好回答,那我们能不能自己模仿实现Foreach呢?
c、Foreach内部原理:IEnumerable接口 自己实现IEnumerable
复制代码 代码如下:

using System.Collections;//引入IEnumerable所在命名空间
namespace IEnumerater {
class MyList : IEnumerable {//实现接口IEnumerable 它就一个IEnumerator声明枚举器的方法
ArrayList ary = new ArrayList();
public void Add(string name) {
ary.Add(name);
}
//自己写索引器 形式类似属性 作用类似枚举 方便快捷的方式 访问集合中的元素
public string this[ int index] {//int类型
get {
return ary[index].ToString();
} //index>ary.Count时超出索引界限
//set { }
}
public int this[ string name] {//string类型 通过name查找索引 参数类型自己决定 返回类型自己决定
get {
for(int i = 0; i < ary.Count; i++) {
if(ary[i] == name) {
return i;
}
}
return -1;
}
}
public IEnumerator GetEnumerator() {//IEnumerator F12跳转定义这里可以发现foreach只允许读取数据,而不能修改数据
for(int i = 0; i < ary.Count; i++) {
yield return ary[i].ToString();// yield关键字 可以看到 实现IEnumerator(枚举器)接口中MoveNext(指向下一条)方法 和Current(获取当前元素 因为只有get 所以可以理解为什么foreach不能修改值的原因了) 以及Reset重置索引
}
}
}
}

d、调用自己的IEnumerable
复制代码 代码如下:

using System;
namespace IEnumerater {
class Program {
static void Main(string[] args) {
//自己写一个类 实现了IEnumerable接口的getEnumerator()方法 就可以实现foreach的操作
MyList mylist = new MyList();
mylist.Add( "wanghao");//调用自己的add(string)方法
mylist.Add( "nihao");
mylist.Add( "buhao");
Console.WriteLine(mylist[1]);//使用自己的索引
Console.WriteLine(mylist["nihao" ].ToString());
foreach(string item in mylist) {
Console.WriteLine(item);
//item = "hello"; 不能使用foreach改变值
}
Console.Read();
}
}
}

总结
如果一个类进行foreach的话,该类必须实现IEnumerable,集合要支持foreach方式的遍历,必须实现IEnumerable接口(还要以某种方式返回实现了IEnumerator 的对象)
更多精彩内容其他人还在看

.NET Core源码解析配置文件及依赖注入

这篇文章我们设计了一些复杂的概念,因为要对ASP.NET Core的启动及运行原理、配置文件的加载过程进行分析,依赖注入,控制反转等概念的讲解等
收藏 0 赞 0 分享

.NET Corek中Git的常用命令及实战演练

这篇文章将通过故事的形式从Git的历史谈起,并讲述Git的强大之处。然后通过实战演练教你如何在Github以及码云上托管我们的代码并进行代码的版本控制
收藏 0 赞 0 分享

Asp.Net Core WebAPI使用Swagger时API隐藏和分组详解

这篇文章主要给大家介绍了关于Asp.Net Core WebAPI使用Swagger时API隐藏和分组的相关资料,文中通过示例代码介绍的非常详细,对大家学习或者使用Asp.Net Core具有一定的参考学习价值,需要的朋友们下面来一起学习学习吧
收藏 0 赞 0 分享

如何利用FluentMigrator实现数据库迁移

这篇文章主要给大家介绍了关于如何利用FluentMigrator实现数据库迁移的相关资料,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面来一起学习学习吧
收藏 0 赞 0 分享

ASP.NET Core利用Jaeger实现分布式追踪详解

这篇文章主要给大家介绍了关于ASP.NET Core利用Jaeger实现分布式追踪的相关资料,文中通过示例代码介绍的非常详细,对大家学习或者使用ASP.NET Core具有一定的参考学习价值,需要的朋友们下面来一起学习学习吧
收藏 0 赞 0 分享

浅谈从ASP.NET Core2.2到3.0你可能会遇到这些问题

这篇文章主要介绍了ASP.NET Core2.2到3.0可能会遇到的问题,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
收藏 0 赞 0 分享

详解.net core webapi 前后端开发分离后的配置和部署

这篇文章主要介绍了.net core webapi 前后端开发分离后的配置和部署,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
收藏 0 赞 0 分享

详解ASP.Net Core 中如何借助CSRedis实现一个安全高效的分布式锁

这篇文章主要介绍了ASP.Net Core 中如何借助CSRedis实现一个安全高效的分布式锁,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
收藏 0 赞 0 分享

.net 4.5部署到docker容器的完整步骤

这篇文章主要给大家介绍了关于.net 4.5部署到docker容器的完整步骤,文中通过示例代码介绍的非常详细,对大家学习或者使用.net4.5具有一定的参考学习价值,需要的朋友们下面来一起学习学习吧
收藏 0 赞 0 分享

.net core并发下线程安全问题详解

这篇文章主要给大家介绍了关于.net core并发下线程安全问题的相关资料,文中通过示例代码介绍的非常详细,对大家学习或者使用.net core具有一定的参考学习价值,需要的朋友们下面来一起学习学习吧
收藏 0 赞 0 分享
查看更多