2010-03-29 13 views
12

Używam klasy Dictionary<int, MyType>. Ta klasa implementuje interfejs, który wymaga zwrócenia numeru IList<MyType>. Czy istnieje prosty sposób na przeniesienie jednego do drugiego (bez skopiowania całej rzeczy)?Konwertuj słownik <MyType>. Kolekcja wartości do IList <MyType>

Moje obecne rozwiązanie następuje:

private IList<MyType> ConvertToList(Dictionary<int, MyType>.ValueCollection valueCollection) 
{ 
    List<MyType> list = new List<MyType>(); 
    list.AddRange(valueCollection); 
    return list; 
} 
+0

Każde rozwiązanie opublikowane do tej pory obejmuje kopiowanie całej kolekcji. ** Przeczytaj pytanie **. – SLaks

+0

@SLaks: Powiedziałem to bezpośrednio w mojej odpowiedzi ... (która nadal wymaga kopiowania). –

+0

Czy jest jakaś istotność dla parametru key "int", czy jest to typ arbitralny? –

Odpowiedz

20

Musisz zrobić kopię, ale to chyba dobrze. W C# 2 twój obecny kod jest prawie najczystszy, jaki możesz zrobić. Zostałaby poprawiona poprzez bezpośrednie skonstruowanie listy wartości (List<MyType> list = new List<MyType>(valueCollection);), ale kopia nadal będzie wymagana.

Używanie LINQ w C# 3, jednak będzie można zrobić:

myDictionary.Values.ToList(); 

Mając na uwadze powyższe, nie będę (prawdopodobnie) starają się unikać kopię. Zwracanie kopii twoich wartości wydaje się być bezpieczniejsze, ponieważ zapobiega wywoływaniu problemów przez wywołującego, jeśli próbują zmodyfikować swoją kolekcję. Zwracając kopię, wywołujący może wykonać list.Add(...) lub list.Remove(...) bez powodowania problemów z klasą.


Edit: Biorąc pod uwagę swój komentarz poniżej, jeśli wszystko co chcesz jest IEnumerable<T> z Count, można po prostu wrócić ICollection<T>. Ten jest bezpośrednio realizowane przez ValueCollection, co oznacza, że ​​można po prostu wrócić wartości słownika bezpośrednio, bez kopiowania:

private ICollection<MyType> ConvertToList(Dictionary<int, MyType>.ValueCollection valueCollection) 
{ 
    return valueCollection; 
} 

(prawda, metoda ta staje się naprawdę bezużyteczny w tym przypadku - ale chciałem wykazać go do ty ...)

+0

@Slaks: Stąd następne zdanie: "Możesz bezpośrednio utworzyć listę swoich wartości";) To nie jest dużo lepsze, chociaż ponieważ jest to ICollection , będzie bardziej wydajne (ponieważ liczba jest znana z góry). –

+0

@Slaks: To lepiej? Zrobiłem to wyraźniej. –

+0

Dzięki za doskonałą odpowiedź. Interfejs ICollection idealnie pasuje do moich potrzeb. –

0

Można użyć konstruktora: (. Zmieniano usunąć twierdzenie nie jestem pewien na 100%)

public IList<MyType> MyValues 
{ 
    get { return new List<MyType>(myDictionary.Values); } 
} 

+0

To nadal tworzy kopię kolekcji. – mcNux

4

Jak około

Dictionary<int, MyType> dlist = new Dictionary<int, MyType>(); 
IList<MyType> list = new List<MyType>(dlist.Values); 
+2

To nadal kopiuje kolekcję. – SLaks

2

To nie jest możliwe.

Słownik (w tym jego kolekcja Values) jest z natury nieuporządkowanymi kolekcjami; jego kolejność zmieni się w oparciu o hashkody kluczy. Dlatego właśnie ValueCollection nie implementuje w pierwszej kolejności IList<T>.

Jeśli naprawdę chciał, mógłbyś uczynić klasy otoki, który implementuje IList i otacza ValueCollection, używając foreach pętlę w indekser. Jednak nie jest to dobry pomysł.

+0

@SLaks Nie jestem wybredny w kwestii zamówienia. To, czego chcę, to niezliczona liczba. Jeśli jest lepszy interfejs, daj mi znać. –

+0

@C. Ross: Zobacz moją edycję, a potem ... –

Powiązane problemy