2009-05-12 15 views
9

Mam klasę, która zawiera kolekcję. Chcę podać metodę lub właściwość, która zwraca zawartość kolekcji. Jest ok, jeśli wywoływanie klas może modyfikować poszczególne obiekty, ale nie chcę, aby dodawały lub usuwały obiekt z rzeczywistej kolekcji. Kopiowałem wszystkie obiekty do nowej listy, ale teraz myślę, że mogę po prostu zwrócić listę jako IEnumerable <>.Jak zwrócić tylko do odczytu kopię kolekcji

W uproszczonym przykładzie poniżej GetListC jest najlepszym sposobem, aby zwrócić wersję tylko do odczytu kolekcji?

public class MyClass 
{ 
    private List<string> mylist; 

    public MyClass() 
    { 
     mylist = new List<string>(); 
    } 

    public void Add(string toAdd) 
    { 
     mylist.Add(toAdd); 
    } 

    //Returns the list directly 
    public List<String> GetListA 
    { 
     get 
      { 
      return mylist; 
      } 
    } 

    //returns a copy of the list 
    public List<String> GetListB 
    { 
     get 
     { 
      List<string> returnList = new List<string>(); 

      foreach (string st in this.mylist) 
      { 
       returnList.Add(st); 
      } 
      return returnList; 
     } 
    } 

    //Returns the list as IEnumerable 
    public IEnumerable<string> GetListC 
    { 
     get 
     { 
      return this.mylist.AsEnumerable<String>(); 
     } 

    } 

} 

Odpowiedz

23

Można użyć List(T).AsReadOnly():

return this.mylist.AsReadOnly() 

który zwróci ReadOnlyCollection.

+0

To w przestrzeni nazw System.Collections.ObjectModel. – mbillard

+0

Huh, jestem zaskoczony, że to zepsułem. –

+2

Oczywiście trzeba będzie zastąpić typ zwrotu z listy na ReadOnlyCollection lub ICollection lub IEnumrable Yona

2

Wystarczy użyć klasy ReadOnlyCollection, jest wspierany od .NET 2.0

0

Użyj ogólnej klasy ReadOnlyCollection (Collection.AsReadOnly()). Nie kopiuje żadnych obiektów, które mogą mieć dziwne wyniki, gdy kolekcja podstawowa zostanie zmieniona.

 var foo = new List<int> { 3, 1, 2 }; 
     var bar = foo.AsReadOnly(); 

     foreach (var x in bar) Console.WriteLine(x); 

     foo.Sort(); 

     foreach (var x in bar) Console.WriteLine(x); 

Ale jeśli nie chcesz kopii, to najlepsze rozwiązanie.

-2

Wolę powracać IEnumerable, ale nie trzeba rzucać. Wystarczy zrobić

public IEnumerable<string> StringList { get { return myList; } 

List<string> jest IEnumerable<string>

+0

Problem z tym, że wykonywanie takich czynności, jak określanie liczby, staje się bardzo kosztowne. –

+7

Prawdziwy problem polega na tym, że konsument kodu może w dowolnej chwili przesłać go z powrotem na listę i zmodyfikować listę. – Yona

+0

nie zawsze potrzebujesz licznika, a celem jest odsłonięcie interfejsu, który zapewnia wszystkie funkcje, których potrzebujesz, i żaden nie – Robert