博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
IEnumerable和IEnumerable<T>接口
阅读量:6154 次
发布时间:2019-06-21

本文共 3997 字,大约阅读时间需要 13 分钟。

IEnumerableIEnumerable<T>接口在.NET中是非常重要的接口,它允许开发人员定义foreach语句功能的实现并支持非泛型方法的简单的迭代,IEnumerableIEnumerable<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类的属性,这些属性包括NameAgeNameAge属性分别用于描述Person的名字和年龄,用于数据初始化。初始化之后的数据就需要创建一系列Person对象,通过这些对象的相应属性能够进行对象的访问和遍历,示例代码如下所示。 

 

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

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

 
private
 Person[] per;
        
public Person(Person[] array)                                                    
//
重载构造函数,迭代对象
        {
            per = 
new Person[array.Length];                                       
//
创建对象
            
for (
int i = 
0; 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 = -
1;                                                                           
//
设置“指针”
    
public PersonEnum(Person[] list)
    {
        _per = list;                                                                             
//
实现list
    }
    
public 
bool MoveNext()                                                              
//
实现向前移动
    {
        position++;                                                                            
//
位置增加
        
return (position < _per.Length);                                        
//
返回布尔值
    }
    
public 
void Reset()                                                                      
//
位置重置
    {
        position = -
1;                                                                         
//
重置指针为-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]                                    
//
同样初始化并定义2个Person对象
            {
                
new Person(
"
guojing
",
"
21
"),                              
//
构造创建新的对象
                
new Person(
"
muqing
",
"
21
"),                              
//
构造创建新的对象
            };
            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支持数组的查询,开发人员不必自己手动创建IEnumerableIEnumerable<T>接口以支持某个类型的foreach编程方法,但是IEnumerableIEnumerable<T>LINQ中非常重要的接口,在LINQ中也大量的使用IEnumerableIEnumerable<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内部也大量的使用了IEnumerableIEnumerable<T>接口实现LINQ查询。IEnumerable原本就是.NET Framework中最基本的集合访问器,而LINQ是面向关系(有序N元组集合)的,自然也就是面向IEnumerable<T>的,所以了解IEnumerableIEnumerable<T>LINQ的理解是有一定帮助的

 

转载地址:http://gibfa.baihongyu.com/

你可能感兴趣的文章
Sentinel 1.5.0 正式发布,引入 Reactive 支持
查看>>
数据库之MySQL
查看>>
2019/1/15 批量删除数据库相关数据
查看>>
数据类型的一些方法
查看>>
AOP
查看>>
NGUI Label Color Code
查看>>
Webpack 2 中一些常见的优化措施
查看>>
移动端响应式
查看>>
js中var、let、const的区别
查看>>
简洁优雅地实现夜间模式
查看>>
react学习总结
查看>>
在soapui上踩过的坑
查看>>
MySQL的字符集和字符编码笔记
查看>>
ntpd同步时间
查看>>
must implement java.io.Serializable hessian
查看>>
Microsoft Licenses Flash Lite for Windows Mobile Users
查看>>
HDOJ 2020 绝对值排序
查看>>
HDOJ/HDU 2560 Buildings(嗯~水题)
查看>>
Maven编译时跳过Test
查看>>
Spring Boot 整合Spring Security 和Swagger2 遇到的问题小结
查看>>