IEnumerable和IEnumerator详解
引言
IEnumerable是可枚举的所有非泛型集合的基接口, IEnumerable包含一个方法GetEnumerator(),该方法返回一个IEnumerator;IEnumerator提供通过Current属性以及MoveNext()和Reset()方法来循环访问集合的功能。
IEnumerable 接口
公开枚举数,该枚举数支持在非泛型集合上进行简单迭代。接口源码如下:
public interface IEnumerable
{
[DispId(-), __DynamicallyInvokable]
IEnumerator GetEnumerator();
}
IEnumerator 接口
支持对非泛型集合的简单迭代。接口源码如下:
public interface IEnumerator
{
[__DynamicallyInvokable]
bool MoveNext();
[__DynamicallyInvokable]
object Current { [__DynamicallyInvokable] get; }
[__DynamicallyInvokable]
void Reset();
}
举例说明
示例演示了通过实现IEnumerable和IEnumerator接口来循环访问自定义集合的最佳实践。
定义一个简单的实体类:
public class Person
{
public Person(string name, int age)
{
this.Name = name;
this.Age = age;
}
public string Name;
public int Age;
}
定义一个实体类的集合,继承IEnumerate:
public class People : IEnumerable
{
private Person[] _people;
public People(Person[] pArray)
{
_people = new Person[pArray.Length];
for (int i = ; i < pArray.Length; i++)
{
_people[i] = pArray[i];
}
}
/// <summary>
/// GetEnumerator方法的实现
/// </summary>
/// <returns></returns>
IEnumerator IEnumerable.GetEnumerator()
{
return GetEnumerator();
}
public PeopleEnum GetEnumerator()
{
return new PeopleEnum(_people);
}
}
定义一个枚举器,继承IEnumerator:
public class PeopleEnum : IEnumerator
{
public Person[] _people; /// <summary>
/// 枚举器位于第一个元素之前直到第一个MoveNext()调用。
/// </summary>
private int position = -;
public PeopleEnum(Person[] list)
{
_people = list;
} public bool MoveNext()
{
position++;
return position < _people.Length;
} public void Reset()
{
position = -;
} object IEnumerator.Current => Current; public Person Current
{
get
{
try
{
return _people[position];
}
catch (IndexOutOfRangeException)
{
throw new InvalidOperationException();
}
}
}
}
具体调用:
Person[] peopleArray = new Person[]
{
new Person("张三", ),
new Person("李四", ),
new Person("王五", ),
};
People peopleList = new People(peopleArray); foreach (Person p in peopleList)
Console.WriteLine(p.Name + "\t" + p.Age);
输出:
其中,上边调用中foreach等价于
IEnumerator enumeratorSimple = peopleList.GetEnumerator();
while (enumeratorSimple.MoveNext())
{
Person p = enumeratorSimple.Current as Person;
Console.WriteLine(p?.Name + "\t" + p?.Age);
}
通过例子,可以得出:
- 实现一个自定义集合,继承于IEnumerate,必须实现一个枚举器;
- C# 语言的foreach语句隐藏了枚举数的复杂性,因此, 建议foreach使用, 而不是直接操作枚举器;
- 枚举器可用于读取集合中的数据,但不能用于修改基础集合。
总结
IEnumerable代表继承此接口的类(比如ArrayList,IList,List<T>等)可以获取一个IEnumerator来实现枚举这个类中包含的集合中的元素的功能,是 .NET Framework 中最基本的集合访问器。在编程中,Lambda表达式通过Select()或者Where()返回的变量为IEnumerate<T>,此时我们可以通过foreach遍历。希望本文对你有所帮助,下一篇介绍Lambda中的Select和Where,感兴趣的朋友可以加关注,欢迎留言交流!
IEnumerable和IEnumerator详解的更多相关文章
- IEnumerable和IEnumerator 详解 分类: C# 2014-12-05 11:47 18人阅读 评论(0) 收藏
原:<div class="article_title"> <span class="ico ico_type_Original">&l ...
- IEnumerable和IEnumerator 详解 (转)
原文链接:http://blog.csdn.net/byondocean/article/details/6871881 参考链接:http://www.cnblogs.com/hsapphire/a ...
- IEnumerable和IEnumerator 详解
初学C#的时候,老是被IEnumerable.IEnumerator.ICollection等这样的接口弄的糊里糊涂,我觉得有必要切底的弄清楚IEnumerable和IEnumerator的本质. 下 ...
- IEnumerable和IEnumerator 详解 【转】
初学C#的时候,老是被IEnumerable.IEnumerator.ICollection等这样的接口弄的糊里糊涂,我觉得有必要切底的弄清楚IEnumerable和IEnumerator的本质. 下 ...
- 转载 IEnumerable和IEnumerator 详解
初学C#的时候,老是被IEnumerable.IEnumerator.ICollection等这样的接口弄的糊里糊涂,我觉得有必要切底的弄清楚IEnumerable和IEnumerator的本质. 下 ...
- IEnumerable 使用foreach 详解
自己实现迭代器 yield的使用 怎样高性能的随机取IEnumerable中的值 我们先思考几个问题: 为什么在foreach中不能修改item的值? 要实现foreach需要满足什么条件? 为什么L ...
- C# ~ 从 IEnumerable / IEnumerator 到 IEnumerable<T> / IEnumerator<T> 到 yield
IEnumerable / IEnumerator 首先,IEnumerable / IEnumerator 接口定义如下: public interface IEnumerable /// 可枚举接 ...
- IEnumerator和IEnumerable详解
IEnumerator和IEnumerable 从名字常来看,IEnumerator是枚举器的意思,IEnumerable是可枚举的意思. 了解了两个接口代表的含义后,接着看源码: IEnumerat ...
- IEnumerable<T> 接口和GetEnumerator 详解
IEnumerable<T> 接口 .NET Framework 4.6 and 4.5 公开枚举数,该枚举数支持在指定类型的集合上进行简单迭代. 若要浏览此类型的.NET Frame ...
随机推荐
- 虚拟环境:virtualenv与virtualenvwrapper
前言: 在使用 Python 开发的过程中,工程一多,难免会碰到不同的工程依赖不同版本的库的问题: 亦或者是在开发过程中不想让物理环境里充斥各种各样的库,引发未来的依赖灾难. 此时,我们需要对于不同的 ...
- DRF框架(django rest framework)
1,DRF框架? Django REST framework 框架是一个用于构建Web API 的强大而又灵活的工具.通常简称为DRF框架 或 REST framework. Django REST ...
- Centos 7修改hostname浅析
之前写过一篇博客"深入理解Linux修改hostname",里面总结了RHEL 5.7下面如何修改hostname,当然这篇博客的内容其实也适用于CentOS 6,但是自CentO ...
- .NET项目中实现多工程文件共用的方法
一处开发,多处同步编辑使用,并且发布时各个项目均可独立 一.直接编辑项目工程文件 .csproj 具体实现为:编辑 .csproj 文件,在<ItemGroup>中添加新的 <Con ...
- 一文搭建自己博客/文档系统:搭建,自动编译和部署,域名,HTTPS,备案等
本文纯原创,搭建后的博客/文档网站可以参考: Java 全栈知识体系.如需转载请说明原处. 第一部分 - 博客/文档系统的搭建 搭建博客有很多选择,平台性的比如: 知名的CSDN, 博客园, 知乎,简 ...
- JavaScript中继承的实现方法--详解
最近看<JavaScript王者归来>中关于实现继承的方法,做了一些小总结: JavaScript中要实现继承,其实就是实现三层含义:1.子类的实例可以共享父类的方法:2.子类可以覆盖父类 ...
- 掌握git命令的正确使用姿势
前言 最近在团队内部发起了一个小的python项目(用tkinter实现一个小工具),但是发现大家对git的使用还不太熟悉,不知道怎么同步代码.解决冲突等等.因为我觉得对测试工程师来说,git应该是必 ...
- 「Luogu 3792」由乃与大母神原型和偶像崇拜
更好的阅读体验 Portal Portal1: Luogu Description 给你一个序列\(a\) 每次两个操作: 修改\(x\)位置的值为\(y\): 查询区间\([l, r]\)是否可以重 ...
- 前端Vue中常用rules校验规则
前提 在 vue开发中,难免遇到各种表单校验,这里整理了网络上和自己平时高频率用到的一些校验方法.如果错误欢迎指出,后期不断补充更新. 1.是否合法IP地址 export function valid ...
- 深入理解@LoadBalanced注解的实现原理与客户端负载均衡
前提 在阅读这篇博客之前,希望你对SpringCloud套件熟悉和理解,更希望关注下微服务开发平台 概述 在使用springcloud ribbon客户端负载均衡的时候,可以给RestTemplate ...