[C#.NET] 建立具有foreach的類別,實作 IEnumerator / IEnumerable
先來看一下這兩這介面的成員,這些成員都是必須要實作的。
public interface IEnumerable
{
IEnumerator GetEnumerator();//傳回會逐一查看集合的列舉程式。
}
public interface IEnumerator
{
// 方法
bool MoveNext();//將列舉值往前推至下集合中的下一個項目。如果成功則返回為 true;如果超過集合結尾,則返回false。
void Reset();//設定列舉值至它的初始位置,這是在集合中第一個元素之前。
// 屬性
object Current { get; }//取得集合中目前的項目。
}
實作 IEnumerable 介面便可以讓類別可以使用foreach語法。
IEnumerator 介面是讓類別支援反覆運算(Iteration)。
接下來用程式碼來實現
首先我先需要一個MemberInform類別裡面有一些屬性
class MemberInfomation
{
public string Name { get; set; }
public int ID { get; set; }
public int Age { get; set; }
}
然後在EnumDemo類別裡繼承IEnumerable與IEnumerator介面,並實作這些方法以及屬性。
class EnumerDemo : IEnumerable, IEnumerator
{
//定義索引
private int index = -1;
private MemberInfomation[] member = new MemberInfomation[3];
public EnumerDemo()
{
member[0] = new MemberInfomation { Name = "Orochi", Age = 24, ID = 1175 };
member[1] = new MemberInfomation { Name = "Blinda", Age = 23, ID = 1265 };
member[2] = new MemberInfomation { Name = "Ninicat", Age = 25, ID = 1295 };
}
#region IEnumerable
//傳回會逐一查看集合的列舉程式。
public IEnumerator GetEnumerator()
{
return (IEnumerator)this;
}
#endregion
#region IEnumerator
//設定列舉值至它的初始位置,這是在集合中第一個元素之前。
public void Reset()
{
index = -1;
}
//取得集合中目前的項目。
public object Current
{
get { return member[index]; }
}
//將列舉值往前推至下集合中的下一個項目
public bool MoveNext()
{
index++;
return index >= member.Length ? false : true;
}
#endregion
}
接著在主程式裡呼叫,很簡單的就讓類別可以用foreach列舉
static void Main(string[] args)
{
EnumerDemo member = new EnumerDemo();
foreach (MemberInfomation item in member)
{
Console.WriteLine("ID:{0}, Name:{1}, Age:{2}", item.ID, item.Name, item.Age);
}
Console.Read();
}
要實現具有foreach的功能還挺麻煩的,除了要定義一個類別之外,還要實作IEnumerator / IEnumerable 這兩個界面,還挺麻煩的,但.NET裡的yield節省了這些麻煩,將Enum類別改成下面的樣子。
class EnumerDemo
{
//定義索引
private int index = 0;
private MemberInfomation[] member = new MemberInfomation[3];
public EnumerDemo()
{
member[0] = new MemberInfomation { Name = "Orochi", Age = 24, ID = 1175 };
member[1] = new MemberInfomation { Name = "Blinda", Age = 23, ID = 1265 };
member[2] = new MemberInfomation { Name = "Ninicat", Age = 25, ID = 1295 };
}
public IEnumerable<MemberInfomation> GetMembers()
{
for (int i = 0; i < member.Length; i++)
{
yield return member[i];
}
}
}
在主程式裡就在GetMembers方法使用foreach,有了yield就可以省掉自定類別實作介面的程式碼。
static void Main(string[] args)
{
EnumerDemo member = new EnumerDemo();
foreach (MemberInfomation item in member.GetMembers())
{
Console.WriteLine("ID:{0}, Name:{1}, Age:{2}", item.ID, item.Name, item.Age);
}
Console.Read();
}
看到這裡可能有人會問:『幹嘛要用foreach來列舉資料,我覺得for迴圈也很好用阿,為何要多此一舉呢?』。是的,沒錯,用for迴圈的確就能處理掉這些工作,在設計模式(Design Patterns)裡有一個模式叫Iterator,它主要是希望把物件巡訪的順序 (iteration) 跟依序拿到物件後要作什麼事 (process) 分開 - 安德魯 。
列舉物件歸列舉,演算法歸演算法,我們不需要演算法怎麼處理,我們只要按它擺放的物件順序拿資料就好了,更是能將程式碼的藕合度降低。
若有謬誤,煩請告知,新手發帖請多包涵
Microsoft MVP Award 2010~2017 C# 第四季
Microsoft MVP Award 2018~2022 .NET