IEnumerable和IEnumerable<T>接口

IEnumerable和IEnumerable接口在.NET中是非常重要的接口,它允許開發人員定義foreach語句功能的實現並支持非泛型方法的簡單的迭代,IEnumerable和IEnumerable接口是.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]                                                      //創建並初始化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();
        }
    }
}
上述代碼創建並初始化了2個Person對象,並通過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支持數組的查詢,開發人員不必自己手動創建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的理解是有一定幫助的。
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章