2012-07-03 7 views
11

Dies ist wahrscheinlich eine einfache Syntax Frage, aber ich kann es nicht herausfinden.IEnumerable mit einem Array implementieren

Normalerweise würde ich dies tun:

public class OrderBook : IEnumerable<PriceLevel> 
{ 
    private readonly List<PriceLevel> PriceLevels = new List<PriceLevel>(); 

    public IEnumerator<PriceLevel> GetEnumerator() 
    { 
     return PriceLevels.GetEnumerator(); 
    } 

    IEnumerator IEnumerable.GetEnumerator() 
    { 
     return PriceLevels.GetEnumerator(); 
    } 
} 

Aber statt einer Liste, ich möchte ein Array verwenden - wie folgt aus:

public class ArrayOrderBook : IEnumerable<PriceLevel> 
{ 
    private PriceLevel[] PriceLevels = new PriceLevel[500]; 

    public IEnumerator<PriceLevel> GetEnumerator() 
    { 
     return PriceLevels.GetEnumerator(); 
    } 

    IEnumerator IEnumerable.GetEnumerator() 
    { 
     return PriceLevels.GetEnumerator(); 
    } 
} 

Die IEnumerator IEnumerable.GetEnumerator() fein zu kompilieren scheint - aber die Öffentlichkeit IEnumerator<PriceLevel> sagt, dass ich eine Art Besetzung brauche - was ist der beste Weg, dies zu tun?

William

+2

Warum? Warum ein Array dafür verwenden? – Oded

+1

'List' wird von einem Array selbst gesichert, so dass Sie nichts gewinnen, außer einer Überkomprimierung Ihrer Arbeit. – Tudor

+1

@Tudor Je nachdem, welche andere Logik in der Klasse verwendet wird, kann es sinnvoller sein, dass 'PriceLevels' ein Array ist (z. B. eine feste Größe). Nichts falsch daran, das umgestalten zu wollen. –

Antwort

14

Try this:

public class ArrayOrderBook : IEnumerable<PriceLevel> 
{ 
    private PriceLevel[] PriceLevels = new PriceLevel[500]; 

    public IEnumerator<PriceLevel> GetEnumerator() 
    { 
     return PriceLevels.AsEnumerable().GetEnumerator(); 
    } 

    IEnumerator IEnumerable.GetEnumerator() 
    { 
     return PriceLevels.GetEnumerator(); 
    } 
} 
+1

Der Typ kann abgeleitet werden. '.AsEnumerable()' funktioniert gut. 'T []' implementiert 'IEnumerable ', aber seine öffentliche Methode für 'GetEnumerator' gibt einen schwach typisierten' IEnumerator' zurück. –

+0

@TimS. Du hast absolut recht! –

6

Wie Sie aus Ihrer eigenen IEnumerable<T> Implementierung sehen können, müssen Sie sowohl eine generische und nicht-generische Version des Verfahrens, um die Schnittstelle zu erfüllen. Da die Methoden dieselbe Signatur haben, muss eine davon eine explizite Schnittstellenimplementierung sein. Im Fall von List ist die generische Version eine Methode in der Klasse und die nicht-generische Version ist eine explizite Schnittstellendefinition, da die generische Version im Allgemeinen nützlicher ist. Im Fall eines Arrays hatte es bereits die nicht-generische Version als Implementierung und es wurde die generische Version der Methode in einer nachfolgenden Version hinzugefügt. Um die brechende Änderung zu vermeiden, ist die generische Version stattdessen die explizite Schnittstellendefinition.

Es gibt eine Reihe von Möglichkeiten, dieses Problem zu lösen. Hier sind drei einfache.

public IEnumerator<PriceLevel> GetEnumerator() 
{ 
    return PriceLevels.AsEnumerable().GetEnumerator(); 
} 


public IEnumerator<PriceLevel> GetEnumerator() 
{ 
    IEnumerable<PriceLevel> enumerator = PriceLevels; 
    return enumerator.GetEnumerator(); 
} 

public IEnumerator<PriceLevel> GetEnumerator() 
{ 
    return ((IEnumerable<PriceLevel>)PriceLevels).GetEnumerator() 
} 
+0

+1 für die umfassendste Antwort. – phoog

4

Guss T[] zum entsprechenden IEnumerable<T>:

public IEnumerator<PriceLevel> GetEnumerator() 
    { 
     return ((IEnumerable<PriceLevel>)PriceLevels).GetEnumerator(); 
    } 
2

Nach ECMA-335 Partition I, §8.9.1, ein Vektortyp (Array eindimensional wie T[]) implementiert, die IList<T>, dass sie impliziert, implementiert auch IEnumerable<T>. Die Implementierung der Methoden ist jedoch explizit. Sie müssen also eine der folgenden Methoden verwenden:

Option 1: Verwenden Sie einfach die implizite Zuweisung von Arrays zu IList<T>.

private IList<PriceLevel> PriceLevels = new PriceLevel[500]; 

Option 2: Lassen Sie die Member-Variable als Array, und verwenden die Methode AsEnumerable Erweiterung. Diese Erweiterungsmethode verwendet eine unterstützte implizite Zuweisung, die einer direkten Umwandlung wie (IEnumerable<PriceLevel>)PriceLevels vorzuziehen ist.

IEnumerator IEnumerable.GetEnumerator() 
{ 
    return PriceLevels.AsEnumerable().GetEnumerator(); 
} 

Artikel zu vermeiden:

  1. Die Cast<T> Methode stellt eine unnötige Typprüfung für jedes Element Ihres Arrays und sollte vermieden werden.
  2. Wenn Sie nur Nicht-Null-Elemente aus der Enumeration einschließen müssen, verwenden Sie die Erweiterungsmethode OfType<T>. Andernfalls führt diese Methode auch eine unnötige Typprüfung für jedes Element ein.
Verwandte Themen