簡體   English   中英

如何在不迭代到最后的情況下放棄IEnumerator?

[英]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");
        }
    }

請記住,在引擎蓋下,迭代器方法會導致創建一個單獨的類,它實現了IEnumerableIEnumerator 通過將清理放在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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM