2010-09-02 8 views
8

Mam klasę, która jest IEnumerable<T>, gdzie chcę mieć różne właściwości, które zapewnia filtrowany dostęp IEnumerable<T>.Czy jest możliwe posiadanie własności, która jest IEnumerable <T>?

Tak na przykład:

class Shape 
    ShapeType = Box/Sphere/Pyramid 

class ShapeCollection : IEnumerable<Shape> 
{ 
    public IEnumerable<Shape> OnlyBox 
    { 
     foreach(var s in this) 
     { 
      if (s.ShapeType == Box) 
       yield return s; 
     } 
    } 
} 

Czy tak powinno być? Tylko nie jestem pewien, o tym całkowicie.

Dzięki.

Odpowiedz

11

Jasne, ale może chcesz przerobić go jako

public IEnumerable<Shape> OnlyBox 
{ 
    get { return this.Where(x => x.ShapeType == ShapeType.Box); } 
} 

który robi dokładnie to samo.

+0

+1 za ekspresję. – Cumbayah

+0

Dzięki, tak, to było trochę niestabilne w mojej głowie. Teraz widzę to wyraźnie. –

+0

WTG w/LINQ FTW. – Randolpho

2

Oczywiście, to powinno zadziałać (o ile widzę), chociaż rozwiązanie @ mquander może być odrobinę bardziej eleganckie.

1

To jest poprawne, ale zbędne, myślę. Jeśli chcesz, aby odsłonić silnie wpisany listę kształtach:

public class Shape 
{ 

} 

public class SomethingThatHasShapes 
{ 
    public List<Shape> Shapes { get; set; } 
    public Boxes 
    { 
     get { return Shapes.Where(s => s.ShapeType = ShapeType.Box); } 
    } 


} 

List<T> klasa implementuje IEnumerable.

+0

Wadą tego jest to, że eksponuje twoją listę na wpływy zewnętrzne. –

+0

Potrzebujesz typu zwrotu na swojej drugiej nieruchomości. –

4
class ShapeCollection : IEnumerable<Shape> 
{ 
    public IEnumerable<Shape> OnlyBoxes 
    { 
     get { return this.Where(s => s.ShapeType == Box); } 
    } 
} 

Brakowało ci nawiasu get /, aby było to metodą. Co to jest Box, masz na myśli ShapeType.Box? Może również zmienić nazwę na OnlyBoxes, wydaje się bardziej opisowa.

+0

Nikt mnie nie głosuje, moja reputacja jest dobra, tak jak jest. –

+0

Dzięki, Głosowałem za tobą. Napisałem ten kod, ponieważ nie korzystałem z VS i nie chciałem napisać tego wszystkiego. –

1

Osobiście uważam, że twoja własność OnlyBox jest zbędna. Ponieważ użytkownicy twojej klasy zawsze będą mieli możliwość korzystania z Linq jak poniżej z tą samą wydajnością. Więc chyba można to zrobić lepiej niż metody LINQ, myślę, że to jest w porządku, aby pozostawić go do użytkownika klasy takich jak:

var filtered = shapeCol.Where(s => s.ShapeType == Box); 

Ale jeśli chcesz właściwość, zamiast:

foreach(var s in this) 
{ 
    if (s.ShapeType == Box) 
     yield return s; 
} 

można napisać:

return this.Where(s => s.ShapeType == Box); 
+0

Dzięki, pomysł został uproszczony, ale w rzeczywistości kod do filtrowania jest bardzo brzydki, ponieważ jest to opakowanie dla klasy niezarządzanej. Chciałem więc uczynić go nieco wyższym poziomem dla użytkowników i dla mnie. –

1

bardziej LINQ jak moda byłoby dostarczenie sposobu kolekcji:

public IEnumerable<Shape> Boxes() 
{ 
    return this.Where(ss => ss.ShapeType == ShapeType.Box); 
} 

Albo po prostu posiadające użytkownicy zrobić WHERE:

// gather boxes 
var query = from shape in shapes 
      where shape.ShapeType == ShapeType.Box 
      select shape; 

przeciwnym razie nic złego IEnumerable jako własność (zachowując właściwości umysł powinien być tak prosty, że rzadko generują wyjątki).

0

Tak. To, co masz, jest dobre. Możesz przekonwertować do lambda, jeśli wolisz jego ekspresyjność, choć wersja lambda może być czasami mniej wydajna (nie tak bardzo, że zmieniam wersję lambda na 2.0, chyba że okaże się problematyczna, ale na tyle, że nie chciałbym zmienić całkowicie dobry styl 2.0 na oparty na lambrze, o ile nie uczynił go bardziej ekspresyjnym).