C#学习笔记:foreach原理
这篇随笔是对上一篇随笔C#关键字:yield的扩展。
关于foreach
首先,对于 foreach ,大家应该都非常熟悉,这里就简单的描述下。
foreach 语句用于对实现 System.Collections.IEnumerable 或 System.Collections.Generic.IEnumerable<T> 接口的数组或对象集合中的每个元素进行循环访问,但不能用于在源集合中添加或移除项,否则可能产生不可预知的副作用。如果需要在源集合中添加或移除项,应使用 for 循环。
foreach的原理
foreach语句是被设计用来和可枚举类型一起使用,只要它的遍历对象是可枚举类型(实现了IEnumerable),比如数组。调用过程如下:
- 调用GetEnumerator()方法,返回一个IEnumerator引用。
- 调用返回的IEnumerator接口的MoveNext()方法。
- 如果MoveNext()方法返回true,就使用IEnumerator接口的Current属性获取对象的一个引用,用于foreach循环。
- 重复前面两步,直到MoveNext()方法返回false为止,此时循环停止。
我们可以通过代码模拟foreach的执行过程,如下:
static void Main()
{
int[] arr = { , , , , }; // 声明并初始化数组。
IEnumerator ie = arr.GetEnumerator(); // 调用可枚举类型的GetEnumerator方法获得枚举数对象。
while (ie.MoveNext()) // 调用IEnumerator接口的MoveNext方法移到下一项。实现遍历数组。
{
int i = (int)ie.Current; // 调用IEnumerator接口的Current方法获取当前项。注意它返回的是object类型,需要强制转换类型。
Console.Write("{0} ", i);
}
// Output: 1 2 3 4 5
Console.ReadKey();
}
当然,如果使用foreach的话,就非常简单了,如下:
static void Main()
{
int[] arr = { , , , , };
foreach (int item in arr)
{
Console.Write("{0} ", item);
}
// Output: 1 2 3 4 5
Console.ReadKey();
}
接下来,再看一个复杂点的实例,如下:
class Program
{
static void Main()
{
// Create a Tokens instance.
Tokens f = new Tokens("This is a sample sentence.", new char[] { ' ', '-' }); // Display the tokens.
foreach (string item in f)
{
System.Console.WriteLine(item);
}
// Output:
// This
// is
// a
// sample
// sentence. Console.ReadKey();
}
} public class Tokens : IEnumerable
{
private string[] elements; public Tokens(string source, char[] delimiters)
{
// The constructor parses the string argument into tokens.
elements = source.Split(delimiters);
} // The IEnumerable interface requires implementation of method GetEnumerator.
public IEnumerator GetEnumerator()
{
return new TokenEnumerator(this);
} // Declare an inner class that implements the IEnumerator interface.
private class TokenEnumerator : IEnumerator
{
private int position = -;
private Tokens t; public TokenEnumerator(Tokens t)
{
this.t = t;
} // The IEnumerator interface requires a MoveNext method.
public bool MoveNext()
{
if (position < t.elements.Length - )
{
position++;
return true;
}
else
{
return false;
}
} // The IEnumerator interface requires a Reset method.
public void Reset()
{
position = -;
} // The IEnumerator interface requires a Current method.
public object Current
{
get
{
return t.elements[position];
}
}
}
}
参考文档
- C#中foreach的原来
- http://www.cnblogs.com/mcgrady/archive/2011/11/12/2246867.html
- https://msdn.microsoft.com/zh-cn/library/9yb8xew9%28v=vs.110%29.aspx
C#学习笔记:foreach原理的更多相关文章
- AlloyTouch.js 源码 学习笔记及原理说明
alloyTouch这个库其实可以做很多事的, 比较抽象, 需要我们用户好好的思考作者提供的实例属性和一些回调方法(touchStart, change, touchMove, pressMove, ...
- AlloyFinger.js 源码 学习笔记及原理说明
此手势库利用了手机端touchstart, touchmove, touchend, touchcancel原生事件模拟出了 rotate touchStart multipointStart ...
- lazy-load-img.js 源码 学习笔记及原理说明
lazy-load-img.js? 1. 什么鬼? 一个轻量级的图片懒加载,我个人很是喜欢. 2. 有什么优势? 1.原生js开发,不依赖任何框架或库 2.支持将各种宽高不一致的图片,自动剪切成默认图 ...
- BiLSTM-CRF学习笔记(原理和理解) 维特比
BiLSTM-CRF 被提出用于NER或者词性标注,效果比单纯的CRF或者lstm或者bilstm效果都要好. 根据pytorch官方指南(https://pytorch.org/tutorials/ ...
- JeeSite学习笔记~代码生成原理
1.建立数据模型[单表,一对多表,树状结构表] 用ERMaster建立数据模型,并设定对应表,建立关联关系 2.系统获取对应表原理 1.怎样获取数据库的表 genTableForm.jsp: < ...
- 学习笔记7_Java_day11_JSP原理(5)
4. jsp原理(理解) * jsp其实是一种特殊的Servlet > 当jsp页面第一次被访问时,服务器会把jsp编译成java文件(这个java其实是一个servlet类) > 然后再 ...
- Git学习笔记1--Git原理简单介绍
Git是一个分布式的版本号控制工具,假设想用github等版本号控制系统,核心就是git,以下简介一些git的基础原理,原文:http://git-scm.com/book/en/Getting-St ...
- php学习笔记-foreach循环
顾名思义,foreach是for each的连写,不是for reach.意思就是对数组中的每个元素都要处理一次. foreach只能用来处理数组. 有两种用法,先看第一种. foreach(arra ...
- 深度学习笔记——PCA原理与数学推倒详解
PCA目的:这里举个例子,如果假设我有m个点,{x(1),...,x(m)},那么我要将它们存在我的内存中,或者要对着m个点进行一次机器学习,但是这m个点的维度太大了,如果要进行机器学习的话参数太多, ...
- mysql学习笔记-底层原理详解
前言 我相信每一个程序员都避免不了和数据库打交道,其中Mysql以其轻量.开源成为当下最流行的关系型数据库.Mysql5.0以前以MyISAM作为默认存储引擎,在5.5版本以后,以InnoDB作为默认 ...
随机推荐
- 使用TortoiseGit同步代码到github远程仓库
1.clone github上的代码仓库的URL 可以用HTTPS,SSH, or Subversion 2.同步push 到远程仓库时 要用 SSH地址,同生成SSH private key ,在g ...
- 关于redis,学会这8点就够了
1,redis是什么 redis是一种支持Key-Value等多种数据结构的存储系统.可用于缓存,事件发布或订阅,高速队列等场景.该数据库使用ANSI C语言编写,支持网络,提供字符串,哈希,列表,队 ...
- 描述怎样通过flask+redis+sqlalchemy等工具,开发restful api
flask开发restful api系列(8)-再谈项目结构 摘要: 进一步介绍flask的项目结构,使整个项目结构一目了然.阅读全文 posted @ 2016-06-06 13:54 月儿弯弯02 ...
- unicode和utf-8互转
1.1 ASCII码 我们知道, 在计算机内部, 所有的信息最终都表示为一个二进制的字符串. 每一个二进制位(bit)有0和1两种状态, 因此八个二进制位就可以组合出 256种状态, 这被称为一个字节 ...
- 用OpenLayers开发地图应用
项目背景 最近有一个使用全球地图展示数据的项目,用地图展示数据本身没什么难度,但出于安全和保密的考虑,甲方单位要求项目不能连接外网,只能在内网使用,也就是说,我们不得不在内网中部署一个地图服务器,在这 ...
- zk 05之:ZooKeeper的配置
ZooKeeper 的功能特性通过 ZooKeeper 配置文件来进行控制管理( zoo.cfg 配置文件). ZooKeeper 这样的设计其实是有它自身的原因的.通过前面对 ZooKeeper 的 ...
- AI-Info-Micron-Insight:将您的游戏技能变成一份工作
ylbtech-AI-Info-Micron-Insight:将您的游戏技能变成一份工作 1.返回顶部 1. 将您的游戏技能变成一份工作 听起来不现实? 一位来自著名商学院的教授不这么认为.他认为,金 ...
- 47: error: undefined reference to `QWebView::QWebView(QWidget*)'
QT 5.6版本 用Qt界面设计器打开界面文件,在界面上托入QWebView控件,这时运行会出现错误,错误如下: ......... undefined reference to `QWebView ...
- 面向对象(this关键字)
package com_package2; public class Person3 { private int age; private String name; public int getAge ...
- Javascript Tip(!!)
var a:var b=!!a; a默认是undefined.!a是true,!!a则是false,所以b的值是false,而不再是undefined,也非其它值,主要是为后续判断提供便利. !!一般 ...