2012-05-22 63 views
6

我的當前應用程序中有命令層次結構。C#:枚舉IEnumerable的循環枚舉

public interface ICommand 
{ 
    void Execute(); 
} 

所以,有些命令是有狀態的,有些則不是。

我需要在命令執行過程中以循環的方式枚舉某些命令實現的IEnumerable。

public class GetNumberCommand : ICommand 
{ 
    public GetNumberCommand() 
    { 
     List<int> numbers = new List<int> 
      { 
       1, 2, 3 
      }; 
    } 

    public void Execute() 
    { 
     // Circular iteration here. 
     // 1 => 2 => 3 => 1 => 2 => 3 => ... 
    } 

    public void Stop() 
    { 
     // Log current value. (2 for example) 
    } 
} 

Execute不時被調用,所以需要存儲迭代狀態。

如何實現該圓形枚舉?

我發現兩種解決方案:

  1. 使用IEnumerator<T>接口。 它看起來像:

    if (!_enumerator.MoveNext()) 
    { 
        _enumerator.Reset(); 
        _enumerator.MoveNext(); 
    } 
    
  2. 使用圓形IEnumerable<T>yield永遠相同的序列): Implementing A Circular Iterator

也許有更多的方法來實現它。 你會推薦使用什麼?爲什麼?

回答

1
while (!stop) 
{ 
    foreach (var i in numbers) 
    { 
    // do something 
    } 
} 
+0

在我的情況下,執行'不時被調用,所以有必要存儲迭代狀態。 –

4

而不是處理IEnumerator接口的,

foreach (var x in GetSomething()) 
{ 
    if (someCondition) break; 
} 



public IEnumerable<int> GetSomething() 
{ 
    List<int> list = new List<int>() { 1, 2, 3 }; 
    int index=0; 

    while (true) 
     yield return list[index++ % list.Count]; 
} 
+1

我認爲你很快就會在索引上產生溢出 –

+0

在我的情況下,'Execute'不時被調用,所以有必要存儲迭代狀態。 –

+0

最終看到我的解決方案。您可以將索引存儲在集合中並將其傳遞給迭代器 –

0

我認爲,最舒適的方式時便會來實現自定義集合自定義枚舉,並在其中封裝循環邏輯。

class Collection<T> : IEnumerable<T> 
{ 
    bool circle; 

    List<T> collection = new List<T>(); 

    public IEnumerable<T> IEnumerable<T>.GetEnumerator() 
    { 
    if(circle) return new CustomEnumerator<T>(this); 
    return circle.GetEnumerator(); 
    } 
} 

class CustomEnumerator : Enumerator<T> {} 

這樣的事情...

-1

你可以寫一個圓形枚舉不屈服的回報。

public class CircularEnumerable<T> : IEnumerable<T> 
    { 
    public CircularEnumerable (IEnumerable<T> sequence) 
    { 
     InfiniteLoop = sequence.Concat (this); 
    } 

    private readonly IEnumerable<T> InfiniteLoop; 

    public IEnumerator<T> GetEnumerator() 
    { 
     return InfiniteLoop.GetEnumerator(); 
    } 

    System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator() 
    { 
     return InfiniteLoop.GetEnumerator(); 
    } 
    } 

public class GetNumberCommand : ICommand 
{ 
    public GetNumberCommand() 
    { 
     List<int> numbers = new List<int> 
      { 
       1, 2, 3 
      }; 
     infiniteLoopOnNumbers = new CircularEnumerable<int>(numbers).GetEnumerator(); 
    } 

    IEnumerator<int> infiniteLoopOnNumbers; 

    public void Execute() 
    { 
     infiniteLoopOnNumbers.MoveNext(); 
    } 

    public void Stop() 
    { 
     int value = infiniteLoopOnNumbers.Current; 
    } 
}