2009-08-26 14 views
10

Mam sytuację, w której mam obiekt biznesowy z około 15 właściwościami różnych typów. Obiekt biznesowy musi także implementować interfejs, który posiada następującą metodę:.NET: przełącznik vs słownik dla kluczy strunowych

object GetFieldValue(string FieldName); 

widzę 2 sposoby realizacji tej metody:

użyć instrukcji switch:

switch (FieldName) 
{ 
    case "Field1": return this.Field1; 
    case "Field2": return this.Field2; 
    // etc. 
} 

Użyj słownik (SortedDictionary lub HashTable?):

return this.AllFields[FieldName]; 

Który byłby bardziej wydajny?

Dodano: Zapomniałem powiedzieć. Ta metoda służy do wyświetlania elementu w siatce. Siatka będzie miała kolumnę dla każdej z tych właściwości. Rutynowo będą to siatki z nieco ponad 1000 pozycji w nich. Właśnie dlatego martwię się wydajnością.

Dodany 2:

Oto pomysł: hybrydowe podejście. Utwórz statyczny słownik z kluczami będącymi nazwami właściwości i wartościami będącymi indeksami w tablicy. Słownik jest wypełniany tylko jeden raz podczas uruchamiania aplikacji. Każda instancja obiektu ma tablicę. Tak więc wyszukiwanie będzie wyglądało następująco:

return this.ValueArray[StaticDictionary[FieldName]]; 

Algorytm wypełniania słownika może wykorzystywać odbicie. Samo właściwości zostanie następnie zaimplementowane odpowiednio:

public bool Field1 
{ 
    get 
    { 
     object o = this.ValueArray[StaticDictionary["Field1"]]; 
     return o == null ? false : (bool)o; 
    } 
    set 
    { 
     this.ValueArray[StaticDictionary["Field1"]] = value; 
    } 
} 

Czy ktoś może mieć z tym jakieś problemy?

Można go również posunąć o jeden krok dalej, a wartość ValueArray/StaticDictionary można umieścić w osobnym generycznym typie ValueCollection<T>, gdzie T określał typ odbicia. ValueCollection obsłuży także przypadek, gdy nie ustawiono jeszcze żadnej wartości. Właściwości mogą być następnie zapisywane po prostu jako:

public bool Field1 
{ 
    get 
    { 
     return (bool)this.Values["Field1"]; 
    } 
    set 
    { 
     this.Values["Field1"] = value; 
    } 
} 

I w końcu, ja zaczynam znowu zastanawiać, czy to prosta instrukcja switch nie może być zarówno szybsze i łatwiejsze do utrzymania ....

+0

Czy istnieje powód, dla którego nie wiążesz całego obiektu z siecią jako datarow? –

+0

Prawdę mówiąc, jest to drzewo genealogiczne DevExpress. To jest jak hybryda widoku drzewa/siatki. Zatem dane muszą być hierarchiczne. Interfejs jest dostępny, dzięki czemu TreeList rozumie hierarchię. Prawdopodobnie mógłbym przetłumaczyć to wszystko na DataTable (może to również powiązać), ale jest to dla mnie wygodniejsze w dalszej pracy. –

+0

Chodzi mi o to, że później zrobię inne rzeczy z tą strukturą danych, a nie tylko wyświetlę ją w siatce. –

Odpowiedz

21
switch:  good efficiency, least maintainable 
dictionary: good efficiency, better maintainability 
reflection: least efficient, best maintainability 

Podpowiedź: ignoruj ​​efektywność i martw się tylko o łatwość konserwacji, chyba że faktycznie sprawdziłeś wydajność i okazało się, że jest to problem.

Nie mówię, że odbicie jest jedynym wyborem, tylko że pozwala dodawać/usuwać i zmieniać nazwy w razie potrzeby i nie musi utrzymywać synchronizacji instrukcji switcha lub słownika.

+0

Hmm ... cóż ... ok ... –

+0

Odbicie pozwoliłoby na odkrycie twoich właściwości w czasie wykonywania, więc jeśli dodasz/usuń lub zmień nazwę, nie musisz ponownie pisać żadnego innego kodu (takiego jak instrukcja zmiany lub inicjalizacja słownika). – Ash

+7

Mam tendencję do poznania narzutów związanych z odbiciem, co czyni go mniej konserwowalnym niż metoda słownikowa. Choć może tak być, ponieważ nie używam często refleksji. :) –

7

Ponieważ używasz ciągów słownik będzie prawdopodobnie szybszy. Przełącznik zostanie zasadniczo przetłumaczony na hashtable podczas używania łańcuchów. Ale jeśli używasz ints lub podobnych, zostanie przetłumaczony na tabelę skoku i będzie szybszy.

zobaczyć this answer i pytanie o więcej szczegółów

Najprościej jest profil go i znaleźć na pewno

0

Jak uzyskać wartość każdej nieruchomości będzie prawdopodobnie mniejszy wpływ na ogólną wydajność niż jak cię renderuj swoją siatkę.

Podam przykład: powiedzmy masz następujący realizacji:

private string _latestFieldName = string.Empty; 
private PropertyInfo _propertyInfo; 

object GetFieldValue(string FieldName) 
{ 
    if(FieldName != _latestFieldName) 
    { 
    _propertyInfo = typeof(yourTypeName).GetProperty(FieldName); 
    } 
    return _propertyInfo.GetValue(this,null); 
} 

Jeśli rendering siatka jest renderowanie wiersz naraz przy użyciu odbicia będzie musiał uzyskać PropertyInfo każdym razem . wheras, jeśli renderujesz kolumnę po kolumnie, musisz pobrać właściwość propertyInfo tylko raz dla każdej właściwości, a przewidywanie rozgałęzień będzie prawie za każdym razem, gdy stracisz tylko kilka cykli zegarowych w if. Gdy masz już PropertyInfo i nie musisz rzutować wyniku połączenia do GetValue. używanie odbić przychodzi bardzo blisko korzystania z gettera właściwości, jeśli chodzi o prędkość.

Moim celem jest, zanim zaczniesz optymalizować używanie profilera. (Oczywiście, jeśli nie można również zmienić siatkę nie można naprawdę zoptymalizować go albo)

+0

Nop, nie mogę zmienić siatki. :) –

0

Przełącznik rzeczywiście ma 2 zalety w porównaniu do słownika:

  1. Można tworzyć niestandardowe komunikat wyjątku zalega sekcji, może zawierać nieprawidłową wartość. W przypadku słownika otrzymasz tylko KeyNotFoundException, który nie zawierał nazwy klucza.
  2. Możesz obsługiwać wartości puste. Słownik nie może przechowywać wartości null jako klucza.
Powiązane problemy