Ostatnio wolę mapować relacje 1-1 używając Dictionaries
zamiast Switch
instrukcji. Uważam, że jest to trochę szybsze pisanie i łatwiejsze do mentalnego przetworzenia. Niestety podczas mapowania na nowe wystąpienie obiektu nie chcę go definiować w następujący sposób:
var fooDict = new Dictionary<int, IBigObject>()
{
{ 0, new Foo() }, // Creates an instance of Foo
{ 1, new Bar() }, // Creates an instance of Bar
{ 2, new Baz() } // Creates an instance of Baz
}
var quux = fooDict[0]; // quux references Foo
Biorąc pod uwagę ten konstrukt, zmarnowałem cykle procesora i pamięć, tworząc 3 obiekty, robiąc wszystko, co mogą zawierać ich konstruktory, i ostatecznie wykorzystałem tylko jeden z nich. Wierzę również, że odwzorowanie innych obiektów fooDict[0]
w tym przypadku spowoduje, że będą odwoływać się do tej samej rzeczy, zamiast tworzyć nową instancję Foo
zgodnie z przeznaczeniem. Rozwiązaniem byłoby użycie zamiast tego lambda:
var fooDict = new Dictionary<int, Func<IBigObject>>()
{
{ 0, () => new Foo() }, // Returns a new instance of Foo when invoked
{ 1, () => new Bar() }, // Ditto Bar
{ 2, () => new Baz() } // Ditto Baz
}
var quux = fooDict[0](); // equivalent to saying 'var quux = new Foo();'
Czy dochodzi do tego, że jest to zbyt mylące? Na ()
końcu łatwo tego przeoczyć . A może mapowanie do funkcji / wyrażenia jest dość powszechną praktyką? Alternatywą byłoby użycie przełącznika:
IBigObject quux;
switch(someInt)
{
case 0: quux = new Foo(); break;
case 1: quux = new Bar(); break;
case 2: quux = new Baz(); break;
}
Które wywołanie jest bardziej akceptowalne?
- Słownik, w celu szybszego wyszukiwania i mniejszej liczby słów kluczowych (wielkość liter i podział)
- Przełącznik: częściej spotykany w kodzie, nie wymaga użycia obiektu Func <> do celów pośrednich.
źródło
fooDict[0] is fooDict[0]
). zarówno w przypadku lambda, jak i przełącznika tak nie jestOdpowiedzi:
To interesujące podejście do wzoru fabrycznego . Lubię kombinację słownika i wyrażenia lambda; sprawiło, że spojrzałem na ten pojemnik w nowy sposób.
Ignoruję obawy w twoim pytaniu o cykle procesora, jak wspomniałeś w komentarzach, że podejście inne niż lambda nie zapewnia tego, czego potrzebujesz.
Myślę, że każde podejście (zmiana vs. słownik + lambda) będzie w porządku. Jedynym ograniczeniem jest to, że korzystając ze Słownika, ograniczasz rodzaje danych wejściowych, które możesz otrzymać w celu wygenerowania zwróconej klasy.
Użycie instrukcji switch zapewni większą elastyczność parametrów wejściowych. Jeśli jednak to musi być problem, możesz owinąć słownik wewnątrz metody i uzyskać ten sam efekt końcowy.
Jeśli jest nowy dla Twojego zespołu, skomentuj kod i wyjaśnij, co się dzieje. Zadzwoń po recenzję kodu zespołu, poprowadź ich przez to, co zostało zrobione i poinformuj ich o tym. Poza tym wygląda dobrze.
źródło
case 0: quux = new Foo(); break;
staje się,case 0: return new Foo();
co jest szczerze mówiąc, równie łatwa do napisania i znacznie łatwiejsza do odczytania niż{ 0, () => new Foo() }
C # 4.0 daje ci
Lazy<T>
klasę podobną do twojego drugiego rozwiązania, ale wyraźniej krzyczy „Leniwa inicjalizacja”.źródło
Stylistycznie myślę, że czytelność między nimi jest równa. Łatwiej jest zrobić wstrzyknięcie zależności za pomocą
Dictionary
.Nie zapominaj, że musisz sprawdzić, czy klucz istnieje podczas korzystania z
Dictionary
, i musisz zapewnić rezerwę, jeśli nie istnieje.Wolałbym
switch
instrukcję dla statycznych ścieżek kodu, aDictionary
dla dynamicznych ścieżek kodu (gdzie można dodawać lub usuwać wpisy). Kompilator może być w stanie przeprowadzić statyczną optymalizację z tymswitch
, czego nie może zrobić zDictionary
.Co ciekawe, ten
Dictionary
wzorzec jest czasem tym, co ludzie robią w Pythonie, ponieważ w Pythonie brakujeswitch
instrukcji. W przeciwnym razie używają łańcuchów if-else.źródło
Ogólnie wolałbym nie.
Cokolwiek to zużywa, powinno działać z
Func<int, IBigObject>
. Zatem źródłem mapowania może być słownik lub metoda, która ma instrukcję switch, wywołanie usługi sieci Web lub wyszukiwanie plików ... cokolwiek.Jeśli chodzi o implementację, wolę słownik, ponieważ łatwiej jest go refaktoryzować ze „słownika kodu twardego, klucza wyszukiwania, zwrotu wyniku” do „załadowania słownika z pliku, klucza wyszukiwania, wyniku wyszukiwania”.
źródło