目錄
- 1. 不是必須要IEnumerable和IEnumerator
- 2. 支援繼承IDisposable的IEnumerator
返回目錄
1. 不是必須要IEnumerable和IEnumerator
眾所周知foreach中in後面的對象應該是繼承IEnumerable,程式運行時本質是在調用IEnumerable的GetEnumerator函數來返回一個IEnumerator對象,foreach就是利用IEnumerator對象的Current,MoveNext和Reset成員來進行一段資料的枚舉,但是這個不是必須,比如下面代碼:
class FakeIEnumerable
{
public FakeIEnumerator GetEnumerator()
{
return new FakeIEnumerator(new double[] { 1, 34.3, -43, Double.NaN, 0.0043 });
}
}
class FakeIEnumerator
{
double[] strs;
int curIdx = -1;
public FakeIEnumerator(double[] data)
{
strs = data;
}
public double Current
{
get
{
if (curIdx < 0 || curIdx >= strs.Length)
throw new InvalidOperationException();
return strs[curIdx];
}
}
public bool MoveNext()
{
return ++curIdx < strs.Length;
}
public void Reset()
{
curIdx = -1;
}
}
class Program
{
static void Main()
{
foreach (var item in new FakeIEnumerable())
Console.WriteLine("類型: {0} 值: {1}", item.GetType(), item.ToString());
}
}
上面的兩個類FakeIEnumerable和FakeIEnumerator都沒有繼承IEnumerable和IEnumerator,但是擁有IEnumerable和IEnumerator同名的成員資訊,代碼編譯通過並成功運行。
輸出
類型: System.Double 值: 1
類型: System.Double 值: 34.3
類型: System.Double 值: -43
類型: System.Double 值: NaN
類型: System.Double 值: 0.0043
可為什麼這樣呢?可以參考這個問題下面的回答,講的不能再好了:
http://social.msdn.microsoft.com/Forums/en/netfxbcl/thread/64f3dbe3-5a1a-4a70-904a-792e26376dad
返回目錄
2. 支援繼承IDisposable的IEnumerator
繼承IDisposable的迭代器在foreach結束後會被正確處理掉(調用Dispose方法),另外這個不僅針對真的迭代器(繼承IEnumerator的類),連上面說到的那個偽迭代器類FakeIEnumerator都是同等對待的。
更改上面FakeIEnumerator類代碼
class FakeIEnumerator : IDisposable
{
void IDisposable.Dispose()
{
Console.WriteLine("調用Dispose");
}
/* 後面代碼同上... */
}
運行結果
類型: System.Double 值: 1
類型: System.Double 值: 34.3
類型: System.Double 值: -43
類型: System.Double 值: NaN
類型: System.Double 值: 0.0043
調用Dispose