[英]Why does the using statement work on IEnumerator and what does it do?
回到當我學習foreach
,我在某處讀到:
foreach (var element in enumerable)
{
// do something with element
}
基本上相當於:
using (var enumerator = enumerable.GetEnumerator())
{
while (enumerator.MoveNext())
{
var element = enumerator.Current;
// do something with element
}
}
如果IEnumerator
和IEnumerator<T>
都沒有實現IDisposable
為什么這段代碼甚至可以編譯? C# 語言規范似乎只在IDisposable
的上下文中提到using
語句。
這樣的using
語句有什么作用?
請查看以下有關foreach語句的鏈接。 如果可能,它使用帶有 Dispose 調用的 try/finally 塊。 這就是using語句背后的代碼。
IEnumerator
可能不實現IDisposable
但GetEnumerator()
返回一個IEnumerator<T>
。 來自IEnumerator<T>
上的文檔:
此外,IEnumerator 實現了 IDisposable,這需要您實現 Dispose 方法。 這使您可以在使用其他資源時關閉數據庫連接或釋放文件句柄或類似操作。 如果沒有要處理的額外資源,請提供一個空的 Dispose 實現。
這當然是假設您的枚舉是IEnumerable<T>
而不僅僅是IEnumerable
。 如果您的原始枚舉只是一個IEnumerable
那么它將無法編譯。
似乎還沒有人回答主要問題:
這樣的 using 語句有什么作用?
我將使用我最喜歡的一本書中的一個例子 - Jon Skeet 的C# in Depth 。 您可能會得到由這樣的函數生成的IEnumerator<T>
的結果:
static IEnumerable<string> Iterator()
{
try
{
Console.WriteLine("Before first yield");
yield return "first";
Console.WriteLine("Between yields");
yield return "second";
Console.WriteLine("After second yield");
}
finally
{
Console.WriteLine("In finally block");
}
}
然后你會像這樣使用它:
foreach (string value in Iterator())
{
Console.WriteLine("Received value: {0}", value);
if (value != null)
{
break;
}
}
當我們在第一次迭代時中斷,迭代器只返回序列中的第一個"first"
值。 現在你的迭代器如何“知道”你不會繼續到循環結束,所以它會觸發它的finally
塊? 這里是隱藏的using
語句。 如果您不能使用foreach
循環,那么上面示例中的代碼將如下所示:
IEnumerable<string> enumerable = Iterator();
using (IEnumerator<string> enumerator = enumerable.GetEnumerator())
{
while (enumerator.MoveNext())
{
string value = enumerator.Current;
Console.WriteLine("Received value: {0}", value);
if (value != null)
{
break;
}
}
}
當我們離開隱藏using
語句的范圍時, Dispose()
方法會觸發:
finally
{
Console.WriteLine("In finally block");
}
*以上所有代碼行和部分文本均由 Jon Skeet 提供。 我本可以重寫它,但決定我寧願讓它保持原樣。 如果作者不想讓我分享它 - 我會盡快刪除答案或重寫它。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.