在日常开发工作中,我们发现很多对象都能通过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原理的更多相关文章

  1. Foreach原理

    本质:实现了一个IEnumerable接口, 01.为什么数组和集合可以使用foreach遍历? 解析:因为数组和集合都实现了IEnumerable接口,该接口中只有一个方法,GetEnumerato ...

  2. .net学习之集合、foreach原理、Hashtable、Path类、File类、Directory类、文件流FileStream类、压缩流GZipStream、拷贝大文件、序列化和反序列化

    1.集合(1)ArrayList内部存储数据的是一个object数组,创建这个类的对象的时候,这个对象里的数组的长度为0(2)调用Add方法加元素的时候,如果第一次增加元神,就会将数组的长度变为4往里 ...

  3. 浅析bootstrap原理及优缺点

    网格系统的实现原理,是通过定义容器大小,平分12份(也有平分成24份或32份,但12份是最常见的),再调整内外边距,最后结合媒体查询,就制作出了强大的响应式网格系统   网格系统的实现原理,是通过定义 ...

  4. Array.forEach原理,仿造一个类似功能

    Array.forEach原理,仿造一个类似功能 array.forEach // 设一个arr数组 let arr = [12,45,78,165,68,124]; let sum = 0; // ...

  5. 浅析WebSocket 原理

    浅析WebSocket 原理 长恨此身非我有,何时忘却营营. 简介:先简单了解下WebSocket 原理,日后的使用中再进一步深入研究~ 一.什么是WebSocket WebSocket 是HTML5 ...

  6. 浅析Kerberos原理,及其应用和管理

    文章作者:luxianghao 文章来源:http://www.cnblogs.com/luxianghao/p/5269739.html  转载请注明,谢谢合作. 免责声明:文章内容仅代表个人观点, ...

  7. C#学习笔记:foreach原理

    这篇随笔是对上一篇随笔C#关键字:yield的扩展. 关于foreach 首先,对于 foreach ,大家应该都非常熟悉,这里就简单的描述下. foreach 语句用于对实现  System.Col ...

  8. C#foreach原理

    本文主要记录我在学习C#中foreach遍历原理的心得体会. 对集合中的要素进行遍历是所有编码中经常涉及到的操作,因此大部分编程语言都把此过程写进了语法中,比如C#中的foreach.经常会看到下面的 ...

  9. Foreach 原理

    public class Person { private string[] friends = { "asf", "ewrqwe", "ddd&qu ...

随机推荐

  1. Spark生态

  2. 修改 suse 上的postfix 的日志路径

    刚刚搭建的邮件服务器,没过多久硬盘就爆满了,不得已移动存储,包括日志. 移动存储灰常简单,查找 /etc/postfix/main.cf 中的 data_directory / base_direct ...

  3. IOS7 隐藏状态栏

    - (UIStatusBarStyle)preferredStatusBarStyle { return UIStatusBarStyleLightContent; } // - (BOOL)pref ...

  4. jqueryui.position.js源代码分析

    近期要写前端组件了.狂砍各种组件源代码,这里分析一款jqueryui中的posistion插件,注意,它不是jqueryui widget,首先看下源代码整体结构图 1.看到$.fn.position ...

  5. nginx利用image_filter动态生成缩略图

    转自:http://www.nginx.cn/2160.html "我如今是有些图片须要生成缩略图.这个如今加了image_filter这个已经实现了.但我不知道怎么样才干訪问我上传的原图& ...

  6. android开发学习:打电话和发短信

    1.新建一个android项目 File--New--Other--android application project 填写application name(就是应用的名字.比方:天天酷跑) 填写 ...

  7. 理解class.forName()

    使用jdbc方式连接数据库时会使用一句代码Class.forName(String className).这句话是什么意思呢?首先说一点Class.forName(String className)这 ...

  8. 增强的for循环(或foreach)

    增强的for循环(也称为foreach循环):不用下标变量,顺序的訪问整个数组.不能以其它顺序訪问数组,或者改变数组的元素. for(elementType element: arrayRefVar) ...

  9. [React Fundamentals] Composable Components

    To make more composable React components, you can define common APIs for similar component types. im ...

  10. [React Native] Using the WebView component

    We can access web pages in our React Native application using the WebView component. We will connect ...