[英]List<T>.Enumerator IEnumerator.Reset() method implementation
盡管事實上, 永遠不應該使用IEnumerator.Reset
方法,但我在List<T>
發現了方法實現的奇怪行為。
無論您如何檢查.NET Framework源代碼(使用參考源和ILSpy進行嘗試),該方法都實現如下:
void System.Collections.IEnumerator.Reset() {
if (version != list._version) {
ThrowHelper.ThrowInvalidOperationException(ExceptionResource.InvalidOperation_EnumFailedVersion);
}
index = 0;
current = default(T);
}
但是,看起來這個方法根本就沒有被調用過! 考慮一下代碼:
var list = new List<int>(1) { 3 };
using (var e = list.GetEnumerator())
{
Console.WriteLine(e.MoveNext());
Console.WriteLine(e.Current);
((IEnumerator)e).Reset();
Console.WriteLine(e.MoveNext());
Console.WriteLine(e.Current);
}
很明顯,它應該打印True
和3
兩次。 而不是結果
True
3
False
0
我錯過了任何簡單的解釋?
我錯過了任何簡單的解釋?
是的:你在這里裝箱List.Enumerator
:
((IEnumerator)e).Reset();
這需要現有的副本並重置它 - 將原件保留為一件。
要重置實際的枚舉器,你需要這樣的東西:
var list = new List<int>(1) { 3 };
var e = list.GetEnumerator();
// Can't use "ref" with a using statement
try
{
Console.WriteLine(e.MoveNext());
Console.WriteLine(e.Current);
Reset(ref e);
Console.WriteLine(e.MoveNext());
Console.WriteLine(e.Current);
}
finally
{
e.Dispose();
}
static void Reset<T>(ref T enumerator) where T : IEnumerator
{
enumerator.Reset();
}
這很棘手,因為它使用顯式接口實現。
我沒有測試過,但我認為這對你有用。 顯然,這是一個壞主意,要做到這一點?
編輯:或者,只需將您的變量類型更改為IEnumerator
或IEnumerator<int>
即可。 然后它將被裝箱一次 ,並且Reset
方法將改變盒裝值:
var list = new List<int>(1) { 3 };
using (IEnumerator e = list.GetEnumerator())
{
Console.WriteLine(e.MoveNext());
Console.WriteLine(e.Current);
e.Reset();
Console.WriteLine(e.MoveNext());
Console.WriteLine(e.Current);
}
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.