Foreach遍历
前天在项目中遇到一个问题,foreach遍历过程中修改responses中的对象,其中responses的类型:IEnumerable<Order>,代码如下:
foreach (Order item in responses)
{
if (string.IsNullOrEmpty(item.Creator))
item.Creator = item.Creator2;
}
结果可想而知,response的对象并没有被改变。这是为什么?
弄清楚问题之前需要明白什么是foreach。foreach语句为数组或者对象集合的每一个元素重复一个嵌入语句组,foreach语句用于循环访问集合以获取所需信息,但不应更改集合信息以避免不可预知的负作用。(百度百科)Foreach可以循环访问集合以获取所需信息,为什么foreach不能更改集合信息,什么样的对象能够foreach?这就涉及到IEnumerable和IEnumerator.
IEnumerable和IEnumerator是两个用来实现枚举的接口,相互协助来完成一个具有枚举功能能使用foreach的集合。IEnumerable是一个声明性接口,一个集合对象要foreach,必须实现IEnumerable接口,也既是必须以某种方式返回IEnumerator object。IEnumerator是一个实现式接口,它定义了具体的实现方法。下面首先介绍其定义:
定义IEnumerator接口:
public interface IEnumerator
{
object Current{ get; } bool MoveNext();
void Reset();
}
定义IEnumerable接口:
public interface IEnumerable
{
IEnumerator GetEnumerator();
}
了解定义后,下面实例具体实现IEnumerable和IEnumerator:
public class MyIEnumerator : IEnumerator
{
private string[] strList;
private int position; public MyIEnumerator(string[] strList)
{
this.strList = strList;
position = -;
} public object Current
{
get { return strList[position]; }
} public bool MoveNext()
{
position ++;
if (position < strList.Length) return true;
return false;
} public void Reset()
{
position = -;
}
}
public class MyIEnumerable : IEnumerable
{
private string[] strList; public MyIEnumerable(string[] strList)
{
this.strList = strList;
}
public IEnumerator GetEnumerator()
{
return new MyIEnumerator(strList);
}
}
进行调用:
string[] strList = {"", "", "", ""};
MyIEnumerable my = new MyIEnumerable(strList);
var tt = my.GetEnumerator();
while (tt.MoveNext())
{
Console.Write("{0} ", tt.Current);
}
结果如下:

那么在项目中,如何自定义一个类实现foreach,继承IEnumerable即可,如下实例:
定义实体类:
public class Student
{
public int Id;
public string Name; public Student(int id, string name)
{
Id = id;
Name = name;
}
}
定义student的集合类School,继承IEnumerable集合:
public class School : IEnumerable
{
public Student[] stu = new Student[]; public School()
{
Create();
} public void Create()
{
stu[] = new Student(, "tom");
stu[] = new Student(, "john");
stu[] = new Student(, "mali");
} public IEnumerator GetEnumerator()
{
return this.stu.GetEnumerator();
}
}
使用foreach遍历school:
School school = new School();
foreach (Student item in school.stu)
{
Console.WriteLine("Id is {0} ,Name is {1}", item.Id, item.Name);
}
foreach (Student item in school)
{
Console.WriteLine("Id is {0} ,Name is {1}", item.Id, item.Name);
}
结果如下:

此时一个概念“迭代器”应该进入大家的视野。
迭代器是一种对象,它能够用来遍历标准模板库容器的部分或者全部元素,每个迭代器对象代表容器中的确定地址。
迭代器使开发人员能够在类或者结构中支持foreach迭代,而不必整个实现IEnumerable和IEnumerator接口。只需要提供一个迭代器,即可遍历类中的数据结构。当编译器检测到迭代器时,将自动生成IEnumerable和IEnumerator接口中的相应方法。
另外一个概念yield:yield关键字向编译器指示它所在的方法是迭代器。编译器生成一个类来实现迭代器块中表示的行为。在迭代器块中,yield关键字与return关键字结合使用,向枚举器对象提供值。yield关键字也可与break结合使用,表示迭代结束。
引用:
IEnumerable 使用foreach 详解
IEnumerator和IEnumerable的关系
先说IEnumerable,我们每天用的foreach你真的懂它吗?
Foreach遍历的更多相关文章
- 用<forEach>遍历list集合时,提示我找不到对象的属性
<c:forEach items="${list}" var="item"> <tr> <td>${item.UserId} ...
- 使用yield关键字让自定义集合实现foreach遍历
一般来说当我们创建自定义集合的时候为了让其能支持foreach遍历,就只能让其实现IEnumerable接口(可能还要实现IEnumerator接口) 但是我们也可以通过使用yield关键字构建的迭代 ...
- js中三个对数组操作的函数 indexOf()方法 filter筛选 forEach遍历 map遍历
indexOf()方法 indexOf()方法返回在该数组中第一个找到的元素位置,如果它不存在则返回-1. 不使用indexOf时 var arr = ['apple','orange','pea ...
- mybatis map foreach遍历
mybatis map foreach遍历 转至http://www.cnblogs.com/yg_zhang/p/4314602.html mybatis 遍历map实例 map 数据如下 Map& ...
- foreach遍历遇到的一个细节问题
1.Invalid argument supplied for foreach()警告错误解决办法:foreach遍历之前添加is_array()判断
- IEnumerable 接口 实现foreach 遍历 实例
额 为啥写着东西? 有次面试去,因为用到的时候特别少 所以没记住, 这个单词 怎么写! 经典的面试题: 能用foreach遍历访问的对象的要求? 答: 该类实现IEnumetable 接口 声明 ...
- 实现Foreach遍历
实现Foreach遍历的集合类,需要实现IEnumerable接口,泛型集合则需要实现IEnumerable<T>接口 using System; using System.Collect ...
- foreach遍历扩展(二)
一.前言 假设存在一个数组,其遍历模式是根据索引进行遍历的:又假设存在一个HashTable,其遍历模式是根据键值进行遍历的:无论哪种集合,如果它们的遍历没有一个共同的接口,那么在客户端进行调用的时候 ...
- c#--foreach遍历的用法与split的用法
一. foreach循环用于列举出集合中所有的元素,foreach语句中的表达式由关键字in隔开的两个项组成.in右边的项是集合名,in左边的项是变量名,用来存放该集合中的每个元素. 该循环 ...
随机推荐
- Android -- Activity,Fragment lifecycle
Activity Lifecyce Fragment Lifecycle: 程序运行: 09-16 13:59:22.883 19022-19022/com.example.android.archi ...
- WebView
WebView可以使得网页轻松的内嵌到app里,还可以直接跟js相互调用. webview有两个方法:setWebChromeClient 和 setWebClient setWebClient:主要 ...
- 浏览器-05 HTML和CSS解析1
一个浏览器内核几个主要部分,HTML/CSS解析器,网络处理,JavaScript引擎,2D/3D图形引擎,多媒体支持等; HTML 解析和 DOM 网页基本结构 一个网页(Page),每个Page都 ...
- block fomating context
http://www.w3help.org/zh-cn/kb/010/ 它与普通的块框类似,不同之处在于: 1可以包含浮动元素 2可以阻止外边距折叠 3可以防止元素被浮动元素覆盖 placeholde ...
- Leetcode Copy List with Random Pointer
A linked list is given such that each node contains an additional random pointer which could point t ...
- 【BZOJ】3561: DZY Loves Math VI
题意 求\(\sum_{i=1}^{n} \sum_{j=1}^{m} lcm(i, j)^{gcd(i, j)}\)(\(n, m<=500000\)) 分析 很显然要死推莫比乌斯 题解 设\ ...
- HDU 3306 Another kind of Fibonacci(快速幂矩阵)
题目链接 构造矩阵 看的题解,剩下的就是模板了,好久没写过了,注意取余. #include <cstring> #include <cstdio> #include <s ...
- 最简单的html轮播图制作适合新手
html代码 --------------------------------------------------------------------------------------------- ...
- idea intellij 混淆anroid代码
idea intellij 混淆anroid代码 在project.properties中加入 target=android-14proguard.config=proguard.cfg 点击 Bui ...
- WinForm 中TreeView 控件的使用实例
新建一个窗体,在本窗体界面上需要以下几个按钮 (一个TreeView 一个 TextBox 三个Button 按钮) 后台代码如下: using System; using System.Co ...