前言

在foreach语句中使用枚举,可以迭代数组或集合中的元素,且无须知道集合中的元素的个数。如图显示了调用foreach方法的客户端和集合之间的关系。数组或集合实现带GetEnumerator()方法的IEnumerable接口。GetEnumerator()方法返回一个实现lEnumerable接口的枚举,接着foreach语句就可以使用IEnumerable接口迭代集合了。
GetEnumerator()方法用IEnumerable接口定义,foreach语句并不真的需要在集合类中实现这个接口。有一个名为GetEnumerator()的方法它返回实现了IEnumerator接口的对象就足够了。
先定义一个Person类,这个类有自动实现的属性Firstname和Lastname,以及从Object类重写ToString方法和继承泛型接口IEquatable以比较两个对象是否相等,实现泛型接口IComparer以比较两个对象用来排序。
public class Person : IEquatable<Person>,IComparable<Person>
{
public int Id { get; private set; }
public string FirstName { get; set; }
public string LastName { get; set; }
public override string ToString()
{
return String.Format("{0}, {1} {2}", Id, FirstName, LastName);
}
public bool Equals(Person other)
{
if (other == null)
return base.Equals(other);
return this.FirstName == other.FirstName && this.LastName == other.LastName;
}
public int CompareTo(Person other)
{
if (other == null) throw new ArgumentNullException("other");
int result = this.LastName.CompareTo(other.LastName);
if (result == 0)
{
result = this.FirstName.CompareTo(other.FirstName);
}
return result;
}
}
创建一个三个元素的person数组,现对数组进行排序在用foreach循环访问数组中的元素并输出
Person[] persons = {
new Person { FirstName = "Simen03", LastName = "Go" },
new Person { FirstName = "Simen02", LastName = "Go" },
new Person { FirstName = "Simen01", LastName = "Go" }
};
Array.Sort(persons);
foreach (var person in persons)
Console.WriteLine(person);
分析foreach (var person in persons)Console.WriteLine(person);这段代码IL代码
// loop start (head: IL_009b) IL_008a: ldloc.2 IL_008b: ldloc.3 IL_008c: ldelem.ref IL_008d: stloc.s person IL_008f: ldloc.s person IL_0091: call void [mscorlib]System.Console::WriteLine(object) IL_0096: nop IL_0097: ldloc.3 IL_0098: ldc.i4.1 IL_0099: add IL_009a: stloc.3 IL_009b: ldloc.3 IL_009c: ldloc.2 IL_009d: ldlen IL_009e: conv.i4 IL_009f: blt.s IL_008a // end loop
C#的foreach语句不会解析为IL代码中的foreach语句,C#编译器会把foreach语句转换为IEnumerable接口的方法和属性,foreach语句使用IEnumerator接口的方法和属性,迭代数组中的所有元素,为此,IEnumerator定义了Current属性,来返回光标所在的元素,该接口的MoveNext()方法移动到数组的下一个元素上,如果有这个元素该方法就返回true否则返回false,这个接口的泛型版本IEnumerator派生自接口IDisposable,因此定义了Dispose()方法来清理枚举器占用的资源,使用foreach语句会解析为下面的代码段
IEnumerator enumerator = persons.GetEnumerator();
while (enumerator.MoveNext())
{
var person = enumerator.Current;
Console.WriteLine(person);
}
为了方便的创建枚举器,C#添加了yield语句,yield return 语句返回集合的一个元素,并移动到下一个元素,yield break 可停止迭代。使用迭代块,编译器会生成一个yield类型,其中包含一个状态机,如下代码段所示。yield 类型实现IEnumerator和IDisposable接口的属性和方法。在下面的例子中,可以把yield类型看作内部类Enumerator.外部类的GetEnumerator()方法实例化并返回一个新的yield类型。在yield类型中,变量state定义了迭代的当前位置,每次调用MoveNext()时,当前位置都会改变,MoveNext()封装了迭代代码,并设置了current变量的值,从而使Current属性根据位置返回一个对象。
static void Main(string[] args)
{
var helloCollection = new HelloCollection();
foreach (string s in helloCollection)
{
Console.WriteLine(s);
}
}
public class HelloCollection
{
public IEnumerator<string> GetEnumerator()
{
yield return "Hello";
yield return "World";
}
}
public class HelloCollectionOther
{
public IEnumerator GetEnumertor()
{
return new Enumerator(0);
}
public class Enumerator : IEnumerator<string>, IEnumerator, IDisposable
{
private int state;
private string current;
public Enumerator(int state)
{
this.state = state;
}
public string Current => throw new NotImplementedException();
object IEnumerator.Current
{
get { return current; }
}
public void Dispose()
{
throw new NotImplementedException();
}
public bool MoveNext()
{
switch (state)
{
case 0:current = "hello";
state = 1;
return true;
case 1:current = "world";
state = 2;
return true;
case 2:
break;
}
return false;
}
public void Reset()
{
throw new NotImplementedException();
}
}
}
总结
以上就是这篇文章的全部内容了,希望本文的内容对大家的学习或者工作能带来一定的帮助,如果有疑问大家可以留言交流,谢谢大家对的支持。
# c
# foreach
# 枚举
# foreach语句
# 详解C# 枚举高级用法之Description
# C# 实现枚举转列表
# 简述C#枚举高级战术
# 详细了解C# 枚举与位枚举
# 快速学习c# 枚举
# 细说C#中的枚举:转换、标志和属性
# C#如何获取枚举的描述属性详解
# C#中如何为枚举类型添加描述方法【小技巧】
# C#如何利用反射将枚举绑定到下拉框详解
# C#中变量、常量、枚举、预处理器指令知多少
# C# 枚举的使用简介
# 迭代
# 组中
# 这段
# 重写
# 如图
# 所示
# 会把
# 这篇文章
# 谢谢大家
# 装了
# 转换为
# 方法来
# 创建一个
# 就可以
# 有一个
# 类中
# 客户端
# 其中包含
# 实现了
# 从而使
相关文章:
电影网站制作价格表,那些提供免费电影的网站,他们是怎么盈利的?
网站制作费用多少钱,一个网站的运营,需要哪些费用?
实例解析angularjs的filter过滤器
如何设计高效校园网站?
网站制作价目表怎么做,珍爱网婚介费用多少?
如何用PHP工具快速搭建高效网站?
如何访问已购建站主机并解决登录问题?
如何在沈阳梯子盘古建站优化SEO排名与功能模块?
建站之星logo尺寸如何设置最合适?
如何用狗爹虚拟主机快速搭建网站?
建站IDE高效指南:快速搭建+SEO优化+自适应模板全解析
如何在Golang中使用replace替换模块_指定本地或远程路径
公司网站设计制作厂家,怎么创建自己的一个网站?
如何自己制作一个网站链接,如何制作一个企业网站,建设网站的基本步骤有哪些?
制作农业网站的软件,比较好的农业网站推荐一下?
平台云上自主建站:模板化设计与智能工具打造高效网站
如何高效搭建专业期货交易平台网站?
网站视频怎么制作,哪个网站可以免费收看好莱坞经典大片?
如何快速搭建自助建站会员专属系统?
已有域名如何免费搭建网站?
简历在线制作网站免费,免费下载个人简历的网站是哪些?
建站之星ASP如何实现CMS高效搭建与安全管理?
网站插件制作软件免费下载,网页视频怎么下到本地插件?
深圳网站制作费用多少钱,读秀,深圳文献港这样的网站很多只提供网上试读,但有些人只要提供试读的文章就能全篇下载,这个是怎么弄的?
建站之星如何快速解决建站难题?
如何通过可视化优化提升建站效果?
外汇网站制作流程,如何在工商银行网站上做外汇买卖?
魔方云NAT建站如何实现端口转发?
建站之星客服服务时间及联系方式如何?
如何在宝塔面板中创建新站点?
如何自定义建站之星网站的导航菜单样式?
制作无缝贴图网站有哪些,3dmax无缝贴图怎么调?
香港服务器租用每月最低只需15元?
如何快速建站并高效导出源代码?
XML的“混合内容”是什么 怎么用DTD或XSD定义
制作营销网站公司,淘特是干什么用的?
公司网站建设制作费用,想建设一个属于自己的企业网站,该如何去做?
*服务器网站为何频现安全漏洞?
定制建站策划方案_专业建站与网站建设方案一站式指南
香港服务器建站指南:外贸独立站搭建与跨境电商配置流程
广州网站制作的公司,现在专门做网站的公司有没有哪几家是比较好的,性价比高,模板也多的?
如何在腾讯云免费申请建站?
常州自助建站:操作简便模板丰富,企业个人快速搭建网站
制作网站的基本流程,设计网站的软件是什么?
网站建设制作需要多少钱费用,自己做一个网站要多少钱,模板一般多少钱?
制作假网页,招聘网的薪资待遇,会有靠谱的吗?一面试又各种折扣?
电商平台网站制作流程,电商网站如何制作?
学校免费自助建站系统:智能生成+拖拽设计+多端适配
教育培训网站制作流程,请问edu教育网站的域名怎么申请?
建站之星如何快速更换网站模板?
*请认真填写需求信息,我们会在24小时内与您取得联系。