Wdrażam a DelegateCommand
, kiedy miałem zaimplementować konstruktora (-ów), zaproponowałem dwie następujące opcje projektu:
1: Posiadanie wielu przeciążonych konstruktorów
public DelegateCommand(Action<T> execute) : this(execute, null) { }
public DelegateCommand(Action<T> execute, Func<T, bool> canExecute)
{
this.execute = execute;
this.canExecute = canExecute;
}
2: Posiadanie tylko jednego konstruktora z opcjonalnym parametrem
public DelegateCommand(Action<T> execute, Func<T, bool> canExecute = null)
{
this.execute = execute;
this.canExecute = canExecute;
}
Nie wiem, którego użyć, ponieważ nie wiem, jakie potencjalne zalety / wady wiążą się z jednym z dwóch proponowanych sposobów. Oba można nazwać tak:
var command = new DelegateCommand(this.myExecute);
var command2 = new DelegateCommand(this.myExecute, this.myCanExecute);
Czy ktoś może skierować mnie we właściwym kierunku i wyrazić opinię?
c#
class-design
parameters
constructors
Thomas Flinkow
źródło
źródło
Bitmap.FromFile
) są również opcjąOdpowiedzi:
Wolę wiele konstruktorów niż wartości domyślne i osobiście nie podoba mi się twój przykład dwóch konstruktorów, powinien być zaimplementowany inaczej.
Powodem używania wielu konstruktorów jest to, że główny może po prostu sprawdzić, czy wszystkie parametry nie są zerowe i czy są poprawne, podczas gdy inne konstruktory mogą podać wartości domyślne dla głównego.
Jednak w twoich przykładach nie ma między nimi żadnej różnicy, ponieważ nawet drugorzędny konstruktor
null
podaje wartość domyślną, a główny konstruktor musi również znać wartość domyślną. Myślę, że nie powinno.Oznacza to, że byłby czystszy i lepiej oddzielony, gdyby został wdrożony w ten sposób:
zwróć uwagę
_ => true
na główny konstruktor, który teraz sprawdza również wszystkie parametrynull
i nie przejmuje się żadnymi wartościami domyślnymi.Najważniejsza jest jednak rozszerzalność. Wiele konstruktorów jest bezpieczniejszych, gdy istnieje możliwość, że rozszerzysz swój kod w przyszłości. Jeśli dodasz więcej wymaganych parametrów, a opcjonalne muszą pojawić się na końcu, zepsujesz wszystkie obecne implementacje. Możesz zrobić starego konstruktora
[Obsolete]
i poinformować użytkowników, że zostanie on usunięty, dając im czas na migrację do nowej implementacji bez natychmiastowego łamania kodu.Z drugiej strony włączenie zbyt wielu parametrów jako opcjonalnych byłoby również mylące, ponieważ jeśli niektóre z nich są wymagane w jednym scenariuszu, a opcjonalne w innym, trzeba by studiować dokumentację zamiast wybierać odpowiedniego konstruktora, po prostu patrząc na jego parametry.
źródło
CultureInfo
obiektu. Wolałbym API, które pozwoliłoCultureInfo
parametr mają być dostarczone poprzez dodatkowy parametr, ale podkreślił, że gdyby to było dostarczane to powinno nie byćnull
. W ten sposób przypadkowenull
wartości nie zostaną źle zinterpretowane jako „brak”.Obsolete
starego, jeśli chcesz uniknąć zepsucia, niezależnie od tego, czy masz parametry opcjonalne, czy nie. Z opcjonalnymi parametrami musisz tylko jeObsolete
usunąć.Biorąc pod uwagę, że jedyne, co robisz w konstruktorze, to proste przypisanie, rozwiązanie dla pojedynczego konstruktora może być lepszym wyborem w twoim przypadku. Drugi konstruktor nie zapewnia żadnej dodatkowej funkcjonalności i z projektu konstruktora z dwoma parametrami jasno wynika, że drugi argument nie musi być podawany.
Wiele konstruktorów ma sens, gdy budujesz obiekt z różnych typów. W takim przypadku konstruktory zastępują zewnętrzną fabrykę, ponieważ przetwarzają parametry wejściowe i formatują je do poprawnej wewnętrznej reprezentacji właściwości budowanej klasy. W twoim przypadku tak się jednak nie dzieje, dlatego jeden konstruktor powinien być wystarczający.
źródło
Myślę, że są dwa różne przypadki, w których każde podejście może zabłysnąć.
Po pierwsze, kiedy mamy proste konstruktory (co z mojego doświadczenia zwykle tak jest), rozważyłbym opcjonalne argumenty.
Buuuut, są przypadki, w których opcjonalne argumenty w konstruktorach sprawiają, że sprawy stają się bardziej skomplikowane. Oczywistym przykładem jest to, że te opcjonalne argumenty są wyłączne (tzn. Nie można ich używać razem). Przeciążenie konstruktorów, które zezwalają tylko na rzeczywiście poprawne kombinacje argumentów, zapewniłoby wymuszenie kompilacji tego ograniczenia w czasie. To powiedziawszy, powinieneś także unikać tego przypadku (np. Z wieloma klasami dziedziczącymi z bazy, gdzie każda klasa zachowuje się wyłącznie na zasadzie wyłączności).
źródło