IEnumerable和IEnumerable<T>接口

IEnumerable和IEnumerable<T>接口在.NET中是非常重要的接口,它允许开发人员定义foreach语句功能的实现并支持非泛型方法的简单的迭代,IEnumerable和IEnumerable<T>接口是.NET Framework中最基本的集合访问器,这两个接口对于LINQ的理解是非常重要的。

在面向对象的开发过程中,常常需要创建若干对象,并进行对象的操作和查询,在创建对象前,首先需要声明一个类为对象提供描述,示例代码如下所示。

using System;
using System.Collections.Generic;
using System.Linq; //使用LINQ命名控件
using System.Text; namespace IEnumeratorSample
{
class Person //定义一个Person类
{
public string Name; //定义Person的名字
public string Age; //定义Person的年龄 public Person(string name, string age) //为Person初始化(构造函数)
{
Name = name; //配置Name值
Age = age; //配置Age值
}
}
}

上述代码定义了一个Person类并抽象一个Person类的属性,这些属性包括Name和Age。Name和Age属性分别用于描述Person的名字和年龄,用于数据初始化。初始化之后的数据就需要创建一系列Person对象,通过这些对象的相应属性能够进行对象的访问和遍历,示例代码如下所示。

 class Program
{
static void Main(string[] args)
{
Person[] per = new Person[] //创建并初始化2个Person对象
{
new Person("guojing",""), //通过构造函数构造对象
new Person("muqing",""), //通过构造函数构造对象
};
foreach (Person p in per) //遍历对象
Console.WriteLine("Name is " + p.Name + " and Age is " + p.Age);
Console.ReadKey();
}
}
}

上述代码创建并初始化了2个Person对象,并通过foreach语法进行对象的遍历。但是上述代码是在数组中进行查询的,就是说如果要创建多个对象,则必须创建一个对象的数组,如上述代码中的Per变量,而如果需要直接对对象的集合进行查询,却不能够实现查询功能。例如增加一个构造函数,该构造函数用户构造一组Person对象,示例代码如下所示。

 private Person[] per;
public Person(Person[] array) //重载构造函数,迭代对象
{
per = new Person[array.Length]; //创建对象
for (int i = ; i < array.Length; i++) //遍历初始化对象
{
per[i] = array[i]; //数组赋值
}
}

上述构造函数动态的构造了一组People类的对象,那么应该也能够使用foreach语句进行遍历,示例代码如下所示。

 Person personlist = new Person(per);        //创建对象
foreach (Person p in personlist) //遍历对象
{
Console.WriteLine("Name is " + p.Name + " and Age is " + p.Age);
}

在上述代码的foreach语句中,直接在Person类的集合中进行查询,系统则会报错“ConsoleApplication1.Person”不包含“GetEnumerator”的公共定义,因此foreach语句不能作用于“ConsoleApplication1.Person”类型的变量,因为Person类并不支持foreach语句进行遍历。为了让相应的类能够支持foreach语句执行遍历操作,则需要实现派生自类IEnumerable并实现IEnumerable接口,示例代码如下所示。

 public IEnumerator GetEnumerator()            //实现接口
{
return new GetEnum(_people);
}

为了让自定义类型能够支持foreach语句,则必须对Person类的构造函数进行编写并实现接口,示例代码如下所示。

 class Person:IEnumerable             //派生自IEnumerable,同样定义一个Personl类
{
public string Name; //创建字段
public string Age; //创建字段
public Person(string name, string age) //字段初始化
{
Name = name; //配置Name值
Age = age; //配置Age值
}
public IEnumerator GetEnumerator() //实现接口
{
return new PersonEnum(per); //返回方法
}
}

上述代码重构了Person类并实现了接口,接口实现的具体方法如下所示。

 class PersonEnum : IEnumerator          //实现foreach语句内部,并派生
{
public Person[] _per; //实现数组
int position = -; //设置“指针”
public PersonEnum(Person[] list)
{
_per = list; //实现list
}
public bool MoveNext() //实现向前移动
{
position++; //位置增加
return (position < _per.Length); //返回布尔值
}
public void Reset() //位置重置
{
position = -; //重置指针为-1
public object Current //实现接口方法
{
get
{
try
{
return _per[position]; //返回对象
}
catch (IndexOutOfRangeException) //捕获异常
{
throw new InvalidOperationException(); //抛出异常信息
}
}
}
}

上述代码实现了foreach语句的功能,当开发Person类初始化后就可以直接使用Personal类对象的集合进行LINQ查询,示例代码如下所示。

 static void Main(string[] args)
{
Person[] per = new Person[] //同样初始化并定义2个Person对象
{
new Person("guojing",""), //构造创建新的对象
new Person("muqing",""), //构造创建新的对象
};
Person personlist = new Person(per); //初始化对象集合
foreach (Person p in personlist) //使用foreach语句
Console.WriteLine("Name is " + p.Name + " and Age is " + p.Age);
Console.ReadKey();
}

从上述代码中可以看出,初始化Person对象时初始化的是一个对象的集合,在该对象的集合中可以通过LINQ直接进行对象的操作,这样做即封装了Person对象也能够让编码更加易读。在.NET Framework 3.5中,LINQ支持数组的查询,开发人员不必自己手动创建IEnumerable和IEnumerable<T>接口以支持某个类型的foreach编程方法,但是IEnumerable和IEnumerable<T>是LINQ中非常重要的接口,在LINQ中也大量的使用IEnumerable和IEnumerable<T>进行封装,示例代码如下所示。

public static IEnumerable<TSource> Where<TSource>

(this IEnumerable<TSource> source,Func<TSource, Boolean> predicate)          //内部实现
{
foreach (TSource element in source) //内部遍历传递的集合
{
if (predicate(element))
yield return element; //返回集合信息
}
}

上述代码为LINQ内部的封装,从代码中可以看到,在LINQ内部也大量的使用了IEnumerable和IEnumerable<T>接口实现LINQ查询。IEnumerable原本就是.NET Framework中最基本的集合访问器,而LINQ是面向关系(有序N元组集合)的,自然也就是面向IEnumerable<T>的,所以了解IEnumerable和IEnumerable<T>对LINQ的理解是有一定帮助的

实例:

 using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Collections;
namespace IEnumeratorSample
{ class Person : IEnumerable
{
public string Name;//定义Person的名字
public string Age;//定义Person的年龄
public Person(string name, string age)//为Person初始化(构造函数)
{
Name = name;//配置Name值
Age = age; }
private Person[] per;
public Person(Person[] array)//重载构造函数,迭代对象
{
per = new Person[array.Length];//创建对象
for (int i = ; i < array.Length; i++)//遍历初始化对象
{
per[i] = array[i];//数组赋值
}
}
public IEnumerator GetEnumerator()//实现接口
{
return new PersonEnum(per);
}
}
class PersonEnum : IEnumerator//实现foreach语句内部,并派生
{
public Person[] _per;//实现数组
int position = -;//设置“指针”
public PersonEnum(Person[] list)
{
_per = list;//实现list
}
public bool MoveNext()//实现向前移动
{
position++;//位置增加
return (position < _per.Length);//返回布尔值
} public void Reset()//位置重置
{ position = -;//重置指针为-1
}
public object Current//实现接口方法
{
get
{
try
{
return _per[position];//返回对象
}
catch (IndexOutOfRangeException)//捕获异常
{
throw new InvalidOperationException();//抛出异常信息
}
}
}
} class Program
{ static void Main(string[] args)
{
Person[] per = new Person[]
{
new Person("guojing",""),
new Person("muqing",""),
};
Person personlist = new Person(per);
foreach (Person p in personlist)//遍历对象
{ Console.WriteLine("Name is " + p.Name + " and Age is " + p.Age); }
Console.ReadKey();
}
}
}

IEnumerable和IEnumerable<T>接口的更多相关文章

  1. IEnumerable 与 IEnumerable<T>

    转自:https://blog.csdn.net/qq_21419015/article/details/80495322 IEnumerable 和IEnumerable<T> 接口在 ...

  2. 深入理解IEnumerable和IQueryable两接口的区别

    from:http://blog.csdn.net/ydm19891101/article/details/50969323 无论是在ado.net EF或者是在其他的Linq使用中,我们经常会碰到两 ...

  3. 19.C#逐一介绍IEnumerable和IEnumerable<T>中的扩展方法(10.3-10.5)

    今天没有太多的言语,只有代码,扩展方法多得太多,不能一一列完,书中一些,看多了也就会使用了. //Enumerable.Range 返回起始到结束范围,是一个Enumrable<int>类 ...

  4. 细说 C# 中的 IEnumerable和IEnumerator接口

    我们先思考几个问题: 为什么在foreach中不能修改item的值? 要实现foreach需要满足什么条件? 为什么Linq to Object中要返回IEnumerable? 接下来,先开始我们的正 ...

  5. 迭代器学习之一:使用IEnumerable和IEnumerator接口

    写博客是检验我学习的成果之一以及自我总结的一种方式,以后会经常利用这种方式进行技术交流和自我总结,其中认识不深难免会有错误,但是一直懂得不懂就问,不懂就学的道理! 1.首先看一个简单的列子 , , , ...

  6. foreach为什么要实现IEnumerable接口而不是直接用IEnumerator接口

    在.Net中,要想被foreach遍历,那么目标对象要实现IEnumerable或IEnumerable<T>接口,这个接口有一个方法,GetEnumerator(),返回一个IEnume ...

  7. 理解IEnumerator+IEnumerable这种接口思想

    前言 本文不想过多篇幅来介绍IEnumerator和IEnumerable这两个接口的具体说明,只是把它作一个例子作引言而已,本文将根据自己的理解来描述微软为何要这样设计这种关联风格的接口.这种风格的 ...

  8. C# IEnumerable 和 IEnumerator接口浅析

    温故而知新,可以为师矣,有空经常复习一下基础知识是有必要的,并且能加深理解和记忆. Foreach常用于循环访问集合,对实现IEnumerable的接口的容器进行遍历,IEnumerable和IEnu ...

  9. IEnumerable,ICollection,IList接口问题

    最近有一个疑问:IList已经继承了ICollection<T>,而ICollection<T>继承了 IEnumerable<T>, IEnumerable,那为 ...

随机推荐

  1. 如何使用Log4net创建日志及简单扩展

    第一步:在项目中添加对log4net.dll的引用,这里引用版本是1.2.10.0.第二步:程序启动时读取log4net的配置文件.如果是CS程序,在根目录的Program.cs中的Main方法中添加 ...

  2. C#汉字转拼音(npinyin)将中文转换成拼音全文或首字母

    汉字转拼音貌似一直是C#开发的一个难题,无论什么方案都有一定的bug,之前使用了两种方案. 1.Chinese2Spell.cs 一些不能识别的汉字全部转为Z 2.Microsoft Visual S ...

  3. 【swift学习笔记】三.使用xib自定义UITableViewCell

    使用xib自定义tableviewCell看一下效果图 1.自定义列 新建一个xib文件 carTblCell,拖放一个UITableViewCell,再拖放一个图片和一个文本框到tableviewc ...

  4. SQLite剖析之设计与概念

    1.API 由两部分组成: 核心API(core API)和扩展API(extension API). 核心API的函数实现基本的数据库操作:连接数据库.处理SQL.遍历结果集.它也包括一些实用函数, ...

  5. VMware Workstation中网络连接之桥接、NAT和Host-only

    在Windows XP系统中,安装好VMware Workstation虚拟机软件以后,我们可以查看一下"网络连接"窗口: 在窗口中多出了两块网卡: VMware Network ...

  6. 软件工程(FZU2015)赛季得分榜,第三回合

    目录 第一回合 第二回合 第三回合 第四回合 第五回合 第6回合 第7回合 第8回合 第9回合 第10回合 第11回合 积分规则 积分制: 作业为10分制,练习为3分制:alpha30分: 团队项目分 ...

  7. 面向对象和面向过程的jquery版选项卡

    <!DOCTYPE html><html> <head> <meta charset="UTF-8"> <script src ...

  8. sphinx应用

     sphinx调用原理 只需要提交要查询,sphinx将返回唯一的id号  API调用 1.创建连接 $sphinx = new SphinxClient(); $sphinx->SetServ ...

  9. Python【第四章】:socket

    ocket通常也称作"套接字",用于描述IP地址和端口,是一个通信链的句柄,应用程序通常通过"套接字"向网络发出请求或者应答网络请求. socket起源于Uni ...

  10. spoj 371 Boxes

    N个盒子围成一圈,第i个盒子初始时有Ai个小球,每次可以把一个小球从一个盒子移到相邻的两个盒子之一里.问最少移动多少次使得每个盒子中小球的个数不超过1. ΣAi<=N.1<=N<=1 ...