2012-05-22 189 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; 
    } 
}