浅析foreach原理
在日常开发工作中,我们发现很多对象都能通过foreach来遍历,比如HashTable、Dictionary、数组等数据类型。那为何这些对象能通过foreach来遍历呢?如果写一个普通的Person类,也希望它能通过foreach来遍历应该怎么做?通过查看,发现HashTable、Dictionary、数组等数据类型都实现了一个叫IEnumerable(或其泛型版本)的接口。现在也来尝试下,让Person类实现这个接口(其实实不实现IEnumerable接口不是必须的,只要类型中有public IEnumerator GetEnumerator()这个方法即可):
class Person:IEnumerable
{
public string[] _Name = new string[] { "sk", "jk", "yzk","wcw","ml" };
public string Name { get; set; }
public int Age { get; set; } public IEnumerator GetEnumerator()
{
return new PersonEnumerator(_Name);
}
}
可以看到GetEnumerator()方法需要一个返回值类型为实现了IEnumerator的类型,那就写个类,让其实现IEnumerator接口:
class PersonEnumerator:IEnumerator
{
public PersonEnumerator(string[] name)
{
this._names = name;
} public string[] _names { get; set; }
public int Index = -; public object Current
{
get { return _names[Index]; }
} public bool MoveNext()
{
Index++;
if (Index>=_names.Length)
{
return false;
}
else
{
return true;
}
} public void Reset()
{
Index = -;
}
}
此时再运行程序,就发现Person类可以遍历了。运行结果如下:
aaarticlea/png;base64,iVBORw0KGgoAAAANSUhEUgAAADEAAABbCAIAAABVkfp3AAABSUlEQVRoge3WQRbCIAxFUfa/KlbhZpw4qiJJ2l8hIbX/zao9hytgaXnmq6wGKH1MjzR9mUqSaMK6qqluJTK9WTRtptpkmdx9rWln4PdlxISp8yRvs+YvwtQKpEn9yteErF0EC9nj3SfRphTRhEUTFk1Ylkk+kJa9F6gmebnG1LXYtHO8BPnOrl30e8GhKWgFLz9P6le+JmvgbtVSmKJD3jMXm1JEExZNWCMmr3/o4Dzd1aQ+yqtINU3zgSYVId0TQKDJAhWnswg0WaNGzFPRfrpcL2mayULe6aqo+zzCNHl/jJhcNuygaaWjjSYsmrBowspukueaeryoN8hLX5N1qIWaOoo1mHX/v5ssB7Je00CgqRh7PMiUIpqwaMKiCQs0Wc+nlaZWdntTFWUxFfucp4mmX0xScLj9vUyOw5yKJiyasGjCogmLJqgXyORSIrl5R8IAAAAASUVORK5CYII=" alt="" />
总结,一种类型要想通过foreach遍历,其内部必须有public IEnumerator GetEnumerator()这个方法,而通常的做法是让类型实现IEnumerable接口。
上面的代码还有一个问题,就是Person对象通过foreach遍历时,var并没有推断出是string类型而是object类型,这是因为Current就是object导致的,解决的方案就是泛型,看下面的代码:
class Person
{
public string Name { get; set; }
public int Age { get; set; }
public string[] _Name = new string[] { "zxh", "jk", "ml", "wcw", "sk", "yzk","lmn" }; public IEnumerator<string> GetEnumerator()
{
return new MyClass<string>(_Name);
}
} class MyClass<T>:IEnumerator<T>
{
public MyClass(T[] _Names)
{
this.names = _Names;
}
public T Current
{
get { return names[Index]; }
} private T[] names { get; set; }
private int Index = -; public void Dispose()
{
//throw new NotImplementedException();
} object IEnumerator.Current
{
get { throw new NotImplementedException(); }
} public bool MoveNext()
{
Index++;
if (Index>=names.Length)
{
return false;
}
else
{
return true;
}
} public void Reset()
{
Index = -;
}
}
使用的方法如下:
Person p1 = new Person();
foreach (var item in p1)
{
Console.WriteLine(item);
}
可以看到var已经被推断成string.
下面看一下,自己写的foreach遍历,还是那个Person类(必须有IEnumerator GetEnumerator()这个方法):
把foreach遍历换成下面的代码:
Person p1 = new Person();
IEnumerator enumer = p1.GetEnumerator();
while (enumer.MoveNext())
{
Console.WriteLine(enumer.Current);
}
上面的代码也是能够正常执行的。
扩展:
List<string> strLst = new List<string>(); //查看定义得知,其实现了IEnumerable<T>和IEnumerable2个接口
strLst.AddRange(new string[] { "sk", "jk", "yzk" });
IEnumerator enumer = strLst.GetEnumerator();
while (enumer.MoveNext())
{
Console.WriteLine(enumer.Current);
}
aaarticlea/png;base64,iVBORw0KGgoAAAANSUhEUgAAACoAAAA2CAIAAAA+tZzsAAAA3ElEQVRYhe3VSRKFMAgE0Nz/VDnFv4wbV1pWGvgSGxyK3jmUDzDGttya9iz+lxuBb5kp/hV833IPv1fwdb4fovGcUpA3jP2QNgaje7xZmwqZP2LIG/UR+DPDp1VwfukNZwL5vBRffPHI44ee8ccTeTwM54fk8ca+yyxlbviBf7y/PPMVvK978RKN14xh7Nl8SMTh85eYi89L8cXP85e+EUr33+LFja9DRN5XiovX2h1KDOles9uVTdrFawC5e7EhHDjy7grslY/P1cri8zPv0hvk59cRhQ8ni38GvwIupIVjdGbDCgAAAABJRU5ErkJggg==" alt="" />
一般没人会这么写,遍历一个对象还是直接写foreach。这只不过是其原理。
Dictionary<int, char> dic = new Dictionary<int, char>();
dic.Add(, '壹');
dic.Add(, '贰');
dic.Add(, '叁');
dic.Add(, '肆');
dic.Add(, '伍');
dic.Add(, '陆');
dic.Add(,'柒');
dic.Add(,'扒');
dic.Add(,'玖'); IEnumerator iEnumer = dic.GetEnumerator();
while (iEnumer.MoveNext())
{
KeyValuePair<int, char> item = (KeyValuePair<int, char>)iEnumer.Current;
Console.WriteLine(item.Key+" "+item.Value);
}
浅析foreach原理的更多相关文章
- Foreach原理
本质:实现了一个IEnumerable接口, 01.为什么数组和集合可以使用foreach遍历? 解析:因为数组和集合都实现了IEnumerable接口,该接口中只有一个方法,GetEnumerato ...
- .net学习之集合、foreach原理、Hashtable、Path类、File类、Directory类、文件流FileStream类、压缩流GZipStream、拷贝大文件、序列化和反序列化
1.集合(1)ArrayList内部存储数据的是一个object数组,创建这个类的对象的时候,这个对象里的数组的长度为0(2)调用Add方法加元素的时候,如果第一次增加元神,就会将数组的长度变为4往里 ...
- 浅析bootstrap原理及优缺点
网格系统的实现原理,是通过定义容器大小,平分12份(也有平分成24份或32份,但12份是最常见的),再调整内外边距,最后结合媒体查询,就制作出了强大的响应式网格系统 网格系统的实现原理,是通过定义 ...
- Array.forEach原理,仿造一个类似功能
Array.forEach原理,仿造一个类似功能 array.forEach // 设一个arr数组 let arr = [12,45,78,165,68,124]; let sum = 0; // ...
- 浅析WebSocket 原理
浅析WebSocket 原理 长恨此身非我有,何时忘却营营. 简介:先简单了解下WebSocket 原理,日后的使用中再进一步深入研究~ 一.什么是WebSocket WebSocket 是HTML5 ...
- 浅析Kerberos原理,及其应用和管理
文章作者:luxianghao 文章来源:http://www.cnblogs.com/luxianghao/p/5269739.html 转载请注明,谢谢合作. 免责声明:文章内容仅代表个人观点, ...
- C#学习笔记:foreach原理
这篇随笔是对上一篇随笔C#关键字:yield的扩展. 关于foreach 首先,对于 foreach ,大家应该都非常熟悉,这里就简单的描述下. foreach 语句用于对实现 System.Col ...
- C#foreach原理
本文主要记录我在学习C#中foreach遍历原理的心得体会. 对集合中的要素进行遍历是所有编码中经常涉及到的操作,因此大部分编程语言都把此过程写进了语法中,比如C#中的foreach.经常会看到下面的 ...
- Foreach 原理
public class Person { private string[] friends = { "asf", "ewrqwe", "ddd&qu ...
随机推荐
- Eclipse的DDMS File Explorer无法进入data目录解决方案
进入data目录需要root权限.所以,你的手机要有root才可以.然后做以下步骤就可以了 1.cmd进入platform-tools目录 2.adb shell 3.su(这里要看手机有没有请求ro ...
- nyoj 975 关于521
关于521 时间限制:1000 ms | 内存限制:65535 KB 难度:2 描述 Acm队的流年对数学的研究不是很透彻,但是固执的他还是想一头扎进去. 浏览网页的流年忽然看到了网上有人用玫 ...
- os7新特性之生成二维码
先导入CoreImage.framework 生成二维码 读取二维码
- 解决IE6不支持fixed
/* IE6 是不支持position:fixed的,解决如下*/.right-bar{ _position:absolute;_top:expression(eval(document.docume ...
- http 需要掌握的知识点(一)
超文本传输协议(HTTP,HyperText Transfer Protocol)是互联网上应用最为广泛的一种网络协议.HTTP 也属于 TCP/IP 协议族的子集,想要学习 HTTP ,先需要了解 ...
- 两个简单方法加速DataGridView
两个简单方法加速DataGridView (2009-03-24 16:57:13) 转载▼ 标签: 杂谈 分类: .NET DataGridView虽然好用,但是如果数据量比较大的话就会出现性能的问 ...
- Redis实战之征服 Redis + Jedis + Spring (三)
一开始以为Spring下操作哈希表,列表,真就是那么土.恍惚间发现“stringRedisTemplate.opsForList()”的强大,抓紧时间恶补下. 通过spring-data-redis完 ...
- materialish-progress
https://github.com/pnikosis/materialish-progress materialish-progress-master.zip
- istringstream
编写程序,将来自一个文件中的行保存在一个vector<string>中,然后使用一个istringstream从vector读取数据成员,每次读取一个单词 #include <ios ...
- 学习笔记之SQL
--------参考网站-------- http://en.wikipedia.org/wiki/SQL SQL@Wiki http://en.wikipedia.org/wiki/Delete_% ...