2012-05-22 10 views
6

Es gibt die Befehlshierarchie in meiner aktuellen Anwendung.C#: zirkuläre Aufzählung von IEnumerable

public interface ICommand 
{ 
    void Execute(); 
} 

So sind einige Befehle Stateful, andere nicht.

Ich muss IEnumerable auf zirkuläre Weise für einige Befehlsimplementierung während der Befehlsausführung auflisten.

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 wird von Zeit zu Zeit genannt wird, so ist es notwendig, die Iteration Zustand zu speichern.

Wie implementiert man diese zirkuläre Aufzählung?

habe ich zwei Lösungen gefunden:

  1. die IEnumerator<T> Schnittstelle. Es sieht aus wie:

    if (!_enumerator.MoveNext()) 
    { 
        _enumerator.Reset(); 
        _enumerator.MoveNext(); 
    } 
    
  2. Mit dem Kreis IEnumerable<T> (yield immer die gleiche Sequenz): Implementing A Circular Iterator.

Vielleicht gibt es mehrere Möglichkeiten, um es zu erreichen. Was würden Sie empfehlen und warum?

Antwort

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

In meinem Fall wird 'Execute' von Zeit zu Zeit aufgerufen, daher ist es notwendig, den Iterationsstatus zu speichern. –

4

Statt mit IEnumerator-Schnittstelle des Umgangs,

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

Ich denke, dass Sie sehr bald Überlauf auf Index bekommen werden, wenn das so –

+0

in meinem Fall 'Execute' von Zeit zu Zeit genannt wird, so ist es notwendig, den Iterationszustand zu speichern. –

+0

sehe meine Lösung am Ende. Sie können den Index in der Sammlung speichern und an den Iterator übergeben. –

0

Ich denke, die bequemste Art und Weise wil sein individuelle Sammlung mit benutzerdefinierten Aufzählungs zu implementieren und zirkuläre Logik darin einzukapseln.

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> {} 

so etwas wie dieses ...

-1

Sie eine kreisförmige enumerable ohne Ertrag Erträge schreiben kann.

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; 
    } 
} 
Verwandte Themen