IEnumerable是可枚舉的所有非泛型集合的基接口, IEnumerable包含一個方法GetEnumerator(),該方法傳回一個IEnumerator;IEnumerator提供通過Current屬性以及MoveNext()和Reset()方法來循環通路集合的功能。
引言
IEnumerable是可枚舉的所有非泛型集合的基接口, IEnumerable包含一個方法GetEnumerator(),該方法傳回一個IEnumerator;IEnumerator提供通過Current屬性以及MoveNext()和Reset()方法來循環通路集合的功能。
IEnumerable 接口
公開枚舉數,該枚舉數支援在非泛型集合上進行簡單疊代。接口源碼如下:
public interface IEnumerable
{
[DispId(-4), __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 = 0; 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 = -1;
public PeopleEnum(Person[] list)
{
_people = list;
}
public bool MoveNext()
{
position++;
return position < _people.Length;
}
public void Reset()
{
position = -1;
}
object IEnumerator.Current => Current;
public Person Current
{
get
{
try
{
return _people[position];
}
catch (IndexOutOfRangeException)
{
throw new InvalidOperationException();
}
}
}
}
具體調用:
Person[] peopleArray = new Person[3]
{
new Person("張三", 15),
new Person("李四", 18),
new Person("王五", 21),
};
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,感興趣的朋友可以加關注,歡迎留言交流!
作者:碼探長
公衆号:碼探長
出處:http://www.cnblogs.com/aizai846/
如果你想得到探長更多相關技術文章的消息推送,或者擷取相關下載下傳資源,可以掃描左邊二維碼(或者長按識别二維碼)關注個人公衆号)。
本文版權歸作者和部落格園共有,歡迎轉載,但必須給出原文連結,并保留此段聲明,否則保留追究法律責任的權利。