2009-08-05 22 views
15

Przyglądałem się przykładowemu kodowi i w nim użyłem obiektu ListDictionary do przechowywania niewielkiej ilości danych (około 5-10 obiektów, ale ta liczba może się zmieniać z czasem). Jedyny problem z używaniem tej klasy polega na tym, że w odróżnieniu od wszystkiego, co robię, nie jest generyczna. To znaczy, i popraw mnie, jeśli się mylę, że za każdym razem, gdy wydobywam obiekt z tego miejsca lub wyliczam na nim, że trwa casting. Czy w większym obiekcie znajduje się wystarczająca ilość obiektu Dictionary<T>, aby uzasadnić obciążenie nietypowe ListDictionary?Czy istnieje ogólna alternatywa dla klasy ListDictionary?

Kod, który będzie używał tego obiektu będzie wyliczony na każdym ładowaniu strony, który zgaduję, dlaczego klasa ListDictionary została użyta nad jedną z innych możliwości. Właśnie dlatego chciałbym uzyskać największą wydajność z tej listy danych.

+0

Czy doszedłeś do wniosku w tej sprawie i dokonałeś pomiaru wydajności? Zawsze przeszkadza mi użycie 'Dictionary ', gdy w kolekcji będzie tylko garść przedmiotów, ale wygoda, z jaką się tam znajduje zawsze przeważała nad przeszkodą/ryzykiem związanym z wyborem lub zapisem czegoś innego. Nie jest to wielka kompilacja pod względem wydajności ... chyba że jest. – Rory

Odpowiedz

10

Niestety nie ma generycznego odpowiednika ListDictionary.

Jednak nie powinno to być bardzo trudne do zrealizowania. ListDictionary zasadniczo działa poprzez utrzymywanie połączonej listy par Key/Value i iterowanie nad nimi dla operacji wyszukiwania. Możesz zbudować ListDictionary<TKey,TValue>, owijając LinkedList<T> z bardzo prostymi wyrażeniami LINQ.

Na przykład

public class LinkedDictionary<TKey,TValue> { 
    private LinkedList<KeyValuePair<TKey,TValue>> _list = new LinkedList<KeyValuePair<TKey,TValue>>(); 
    private IEqualityComparer<TKey> _comp = EqualityComparer<TKey>.Default; 

    public void Add(TKey key, TValue value) { 
    _list.Add(new KeyValuePair<TKey,TValue>(key,value)); 
    } 
    public TValue Get(TKey key) { 
    return _list.Where(x => _comp.Equals(x.Key,key)).First().Value; 
    } 
    ... 
} 
+4

Wyobrażam sobie, że używanie LINQ znosiłoby niemal wszystkie zalety wydajności używania ListDictionary, chyba że obliczanie Hash Codes było bardzo kosztowne. – Chuu

+0

@Chuu Ale ListDictionary już wywołuje Equals na każdym kluczu podczas uzyskiwania dostępu do wartości, więc dlaczego powinien być podany LINQ Gdzie mają jakikolwiek negatywny wpływ na wydajność? – sluki

+1

@sluki Przydziały obiektów i delegowane wywołania w porównaniu do pojedynczej metody zawierającej pętlę for. LINQ jest dla czytelności, a nie dla kodu ramowego. – jnm2

4

Jeśli dane przechowywane w ListDictionary są zawsze obiektami (klasami), a nie typami wartości, to prawdopodobnie byłby szybszy niż Słownik <T>. Jeśli będziesz przechowywać typy wartości (struct, int, double, itp.), Koszt boksowania/rozpakowywania najprawdopodobniej zbalansuje rzeczy, a ja poleciłbym Słownikowi <T>.

Podsumowując, chciałbym zauważyć, że różnica w wydajności między tymi dwoma produktami prawdopodobnie będzie najmniejszym z ogólnych problemów związanych z wydajnością. Takie małe rzeczy są na ogół ostatnią rzeczą, o którą należy się martwić, jeśli chodzi o optymalizację wydajności. Przedmioty o większej skali, takie jak wywołania między procesami, interakcja z bazami danych i usługami sieciowymi itp., Powinny być rozwiązywane najpierw, zanim pojawią się wątpliwości co do niewielkiej różnicy w wydajności między listą a słownikiem: <T>.

+0

W pełni zgadzam się, że pod względem wydajności trzeba się martwić o wiele więcej. Powodem, dla którego o to pytam, jest to, że teraz się nad tym zastanawiam i dodam teraz do projektu. Więc jeśli mogę użyć lepszej alternatywy dla klasy ListDictionary od samego początku, to myślę, że to lepsze niż pozostawienie tego tak jak jest. –

1

Proste sprawdzenie MSDN-ListDictionary klasy ujawni

Jest to prosta implementacja IDictionary przy użyciu pojedynczo związaną listę. Jest mniejszy i szybszy niż HashTable , jeśli liczba elementów wynosi 10 lub mniej. Nie należy tego używać, jeśli wydajność jest ważna w przypadku dużych liczb elementów .

1

Możemy użyć,

System.Collections.Generic.Dictionary<Object,Object> dictTemp = new System.Collections.Generic.Dictionary<Object,Object>(); 

Dla przykładu rozważmy następujący,

using System.Collections.Specialized; 

    private ListDictionary g_Attributes = new ListDictionary(); 
    public ListDictionary Attributes 
    { 
     get { return this.g_Attributes; } 
    } 
    public string GetAttribute(string name) 
    { 
     if (HasAttribute(name)) 
      return (string) g_Attributes[name]; 
     else 
      return null; 
    } 
    public bool HasAttribute(string name) 
    { 
     return this.Attributes.Contains(name); 
    } 


    using System.Collection.Generic; 

    private Dictionary<string, object> g_Attributes = new Dictionary<string, object>(); 
    public Dictionary<string, object> Attributes 
    { 
     get { return this.g_Attributes; } 
    } 
    public string GetAttribute(string name) 
    { 
     if (HasAttribute(name)) 
     { 
      return g_Attributes[name].ToString(); 
     } 
     else 
     { 
      return null; 
     } 
    } 
    public bool HasAttribute(string name) 
    { 
    return this.Attributes.ContainsKey(name); 
    } 

myślę, że to będzie ci trochę pomóc!

1

Brak generycznego odpowiednika ListDictionary.

Jeśli korzystanie z tej małej słowniku nie jest zdominowany przez Add i Remove, można rozważyć SortedList<TKey, TValue> które pomimo swojej nazwy, realizuje IDictionary<TKey, TValue>. W przeciwieństwie do ListDictionary, który jest wspierany przez pojedynczo połączoną listę, SortedList jest wspierany przez tablicę posortowanych kluczy i wartości tablicowych.

+0

Myślę, że to jak dotąd najlepsza odpowiedź. –

Powiązane problemy