您的位置:首页 > 其它

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

2013-02-28 00:00 465 查看
自己写一个类模仿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 的对象)
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: