[英]How can I abandon an IEnumerator without iterating to the end?
考慮以下代碼,第一個演示當我們完成對IEnumerable字符串的迭代時執行“清理”。 第二遍是讓我悲傷的原因。 我需要能夠在到達結束之前放棄IEnumerable,然后執行清理代碼。 但是如果你運行這個,你會發現在第二次通過時,清理工作永遠不會開火。
放棄像這樣的IEnumerable的首選方法是什么?
static void Main(string[] args)
{
// first pass
foreach (String color in readColors())
Console.WriteLine(color);
// second pass
IEnumerator<string> reader = readColors().GetEnumerator();
if (reader.MoveNext())
{
Console.WriteLine(reader.Current);
reader.Dispose();
}
}
static IEnumerable<string> readColors()
{
string[] colors = { "red", "green", "blue" };
for (int i = 0; i < colors.Length; i++)
yield return colors[i];
Console.WriteLine("Cleanup goes here");
}
您需要將迭代器方法的主要部分放入try..finally,並使用finally中的清理代碼:
public IEnumerable<string> readColors()
{
try
{
string[] colors = { "red", "green", "blue" };
for (int i = 0; i < colors.Length; i++)
yield return colors[i];
}
finally
{
Console.WriteLine("Cleanup goes here");
}
}
請記住,在引擎蓋下,迭代器方法會導致創建一個單獨的類,它實現了IEnumerable
和IEnumerator
。 通過將清理放在finally塊中,它最終會生成在生成的類' Dispose
方法中。
[ 編輯:(正如其他答案中所指出的)更喜歡using
語句而不是手動調用Dispose
的方法。 我假設你這樣做只是為了突出討論中的問題,但無論如何都值得指出]
這是放棄它的一種方式。 你沒有看到的原因
Cleanup goes here
打印在控制台上是因為for (int i = 0; i < colors.Length; i++)
循環永遠不會運行完成。 請參閱下文,了解如何強制執行清理代碼。
這是另一種方式。 這是在C#中使用IDisposable
對象的首選模式。 這是首選,因為這將導致即使發生異常也會調用IEnumerator.Dispose
。
using (IEnumerator<string> reader = readColors().GetEnumerator()) {
reader.MoveNext();
Console.WriteLine(reader.Current);
}
至於強制執行清理代碼,您可以執行以下操作:
static IEnumerable<string> readColors() {
string[] colors = { "red", "green", "blue" };
try {
for (int i = 0; i < colors.Length; i++) {
yield return colors[i];
}
}
finally {
Console.WriteLine("Cleanup goes here");
}
}
我認為進行清理的首選方法是使用IDisposable
。 在這種情況下,您最好使用特定的IEnumerator<string>
並使用正常的Dispose
方法實現自己的IEnumerable<string>
。 使用foreach
時,您可以免費使用。
class MyEnumerator : IEnumerator<string>
{
// ...
#region IDisposable Members
public void Dispose()
{
// do your cleanup here
throw new NotImplementedException();
}
#endregion
// ...
}
try {
string[] colors = { "red", "green", "blue" };
for (int i = 0; i < colors.Length; i++) {
if(condition == true)
break;
yield return colors[i];
}
}
finally {
Console.WriteLine("Cleanup goes here");
}
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.