Czy wartości logiczne jako argumenty metod są niedopuszczalne? [Zamknięte]

123

Mój kolega twierdzi, że wartości logiczne jako argumenty metod są niedopuszczalne . Zastąpią je wyliczenia. Na początku nie widziałem żadnej korzyści, ale podał mi przykład.

Co jest łatwiejsze do zrozumienia?

file.writeData( data, true );

Lub

enum WriteMode {
  Append,
  Overwrite
};

file.writeData( data, Append );

Teraz rozumiem! ;-)
Jest to zdecydowanie przykład, w którym wyliczenie jako drugi parametr sprawia, że ​​kod jest znacznie bardziej czytelny.

Jaka jest więc Twoja opinia na ten temat?

Thomas Koschel
źródło
7
To była bardzo ciekawa lektura, będę wdrażał tę metodę częściej.
Sara Chipps
hrm, zrobiłem to wcześniej, ale nigdy nie zdawałem sobie sprawy, jak dobry jest to wzór projektowy. więc wyliczenie trafia do pliku?
Shawn
Enum z pewnością ma więcej sensu z semantycznego POV. Z drugiej strony, byłoby interesujące zobaczyć, co wymyślili niektórzy programiści, aby poradzić sobie z logiką rozmytą.
James P.
2
po prostu poprosić o cytryny facet na Adventure czasie, jeśli jest to nie do przyjęcia
ajax333221

Odpowiedzi:

131

Wartości logiczne reprezentują opcje „tak / nie”. Jeśli chcesz przedstawić „tak / nie”, użyj wartości logicznej, powinno to być oczywiste.

Ale jeśli jest to wybór między dwiema opcjami, z których żadna nie jest wyraźnie tak lub nie, wówczas wyliczenie może być czasami bardziej czytelne.

skaffman
źródło
3
Ponadto nazwa metody musi jasno określać, co robi argument tak lub nie, tj. Ustawienie void turnLightOn (bool) clealy true lub yes spowoduje włączenie światła.
simon,
10
Chociaż w tym przypadku może wolałbym mieć turnLightOn () i turnLightOff (), w zależności od sytuacji.
skaffman
14
„TurnLightOn (false)” oznacza „nie włączaj światła”? Confusiong.
Jay Bazuzi,
17
A co powiesz setLightOn(bool).
Finbarr
10
Późny komentarz, ale @Jay Bazuzi: Jeśli twoja metoda nazywa się turnLightOn i podajesz false, równie dobrze możesz w ogóle nie wywoływać metody, przekazując false mówi, że nie włączaj światła. Jeśli światło jest już włączone, nie oznacza to, że je wyłącz, to znaczy nie włączaj go ... Jeśli masz metodę 'turnLight' i wyliczenie z 'On' i 'Off' ma sens, turnLight ( Włącz), włącz Światło (Wyłącz). Zgadzam się ze skaffmanem, ale wolałbym dwie różne jawne metody, turnLightOn () i turnLightOff (). (BTW: to wyjaśnienie w książce Uncle Bobs „Clean Code”)
Phill,
50

Wyliczenia pozwalają również na przyszłe modyfikacje, w których chcesz teraz wybrać trzeci wybór (lub więcej).

Szymon
źródło
3
Lub GetMessage (): TRUE, FALSE lub -1 w Win32.
bk1e
32

Użyj tego, który najlepiej modeluje Twój problem. W podanym przykładzie wyliczenie jest lepszym wyborem. Jednak byłyby inne sytuacje, w których wartość logiczna jest lepsza. Co ma dla ciebie większy sens:

lock.setIsLocked(True);

lub

enum LockState { Locked, Unlocked };
lock.setLockState(Locked);

W tym przypadku mógłbym wybrać opcję logiczną, ponieważ uważam, że jest ona dość jasna i jednoznaczna, i jestem prawie pewien, że mój zamek nie będzie miał więcej niż dwóch stanów. Mimo to drugi wybór jest ważny, ale niepotrzebnie skomplikowany, IMHO.

Jeremy Bourque
źródło
2
w twoim przykładzie wolałbym mieć dwie metody. lock.lock () lock.release () i lock.IsSet, ale wszystko zależy od tego, co ma największy sens dla używanego kodu.
Robert Paulson
3
To uczciwy komentarz, ale myślę, że ilustruje również szerszą kwestię, że istnieje wiele sposobów modelowania danego problemu. Powinieneś używać najlepszego modelu dla swoich okoliczności, a także powinieneś używać najlepszych narzędzi, które zapewnia środowisko programistyczne, aby pasowały do ​​twojego modelu.
Jeremy Bourque,
Całkowicie się zgadzam :), właśnie komentowałem ten konkretny pseudokod, oferując jeszcze jedno ujęcie. Zgadzam się z twoją odpowiedzią.
Robert Paulson,
14

Dla mnie ani użycie wartości logicznych, ani wyliczenia nie jest dobrym podejściem. Robert C. Martin bardzo wyraźnie ujmuje to w swojej wskazówce nr 12 z czystego kodu: Eliminacja argumentów boolowskich :

Argumenty boolowskie głośno deklarują, że funkcja robi więcej niż jedną rzecz. Są mylące i należy je wyeliminować.

Jeśli metoda robi więcej niż jedną rzecz, powinieneś raczej napisać dwie różne metody, na przykład w twoim przypadku: file.append(data)i file.overwrite(data).

Użycie wyliczenia nie wyjaśnia sprawy. To niczego nie zmienia, nadal jest argumentem flagowym.

Pascal Thivent
źródło
7
Czy to nie znaczy, że funkcja, która akceptuje ciąg znaków ASCII o długości N, robi 128 ^ N rzeczy?
detly
@delty Czy to poważny komentarz? Jeśli tak, czy często kodujesz if na wszystkich możliwych wartościach ciągu? Czy jest możliwe porównanie z przypadkiem argumentu logicznego?
Pascal Thivent
Uważam, że są one dopuszczalne, gdy ustawiasz wartość logiczną wewnątrz obiektu. Idealnym przykładem może być setVisible(boolean visible) { mVisible = visible; }. Jaka byłaby alternatywa, którą byś zaproponował?
Brad
2
@Brad show () {mVisible = true} hide () {mVisible = false}
Oswaldo Acauan,
@Oswaldo, chociaż nadal jest poprawne, nie sądzę, aby mieć całkowity sens, aby przypisywać wartość logiczną do różnych wartości za pomocą dwóch różnych metod. Nie masz setIntToOne (), setIntToTwo () setIntToThree (), prawda? Jest to trochę bardziej niejednoznaczne, gdy można mieć tylko dwie możliwe wartości, ale dla zachowania czystości użyj w tym przypadku wartości logicznej.
Brad
13

Myślę, że prawie sam na to odpowiedziałeś, myślę, że celem końcowym jest uczynienie kodu bardziej czytelnym, aw tym przypadku wyliczenie to zrobiło, IMO zawsze najlepiej jest spojrzeć na ostateczny cel, a nie ogólne zasady, może pomyśl o tym więcej jako wskazówka, tj. wyliczenia są często bardziej czytelne w kodzie niż ogólne boole, ints itp., ale zawsze będą wyjątki od reguły.

Tim Jarvis
źródło
13

Pamiętacie pytanie, które Adlai Stevenson zadał ambasadorowi Zorinowi w ONZ podczas kryzysu kubańskiego ?

„Znajdujesz się teraz na sali sądowej opinii światowej i możesz odpowiedzieć tak lub nie . Zaprzeczałeś istnieniu [pocisków] i chcę wiedzieć, czy dobrze cię zrozumiałem… Jestem gotów czekać na moją odpowiedź, aż piekło zamarznie, jeśli to twoja decyzja. "

Jeśli flaga, którą masz w swojej metodzie, ma taki charakter, że możesz ją przypisać do decyzji binarnej , a ta decyzja nigdy nie zmieni się w decyzję trójstronną lub n-kierunkową, wybierz wartość logiczną. Wskazania: Twoja flaga nazywa się isXXX .

Nie rób tego jako logiczne w przypadku czegoś, co jest przełącznikiem trybu . Zawsze jest jeden tryb więcej niż myślałeś, pisząc metodę.

Dylemat jeden więcej trybów dotyczy np. Nawiedzonego systemu Unix, gdzie możliwe tryby uprawnień, które plik lub katalog może mieć obecnie, powodują dziwne podwójne znaczenie trybów w zależności od typu pliku, własności itp.

Thorsten79
źródło
13

Są dwa powody, dla których uważam, że jest to coś złego:

  1. Ponieważ niektórzy ludzie będą pisać metody takie jak:

    ProcessBatch(true, false, false, true, false, false, true);
    

    Jest to oczywiście złe, ponieważ zbyt łatwo jest pomieszać parametry, a nie masz pojęcia, patrząc na to, co określasz. Jednak tylko jeden bool nie jest taki zły.

  2. Ponieważ sterowanie przepływem programu za pomocą prostej gałęzi tak / nie może oznaczać, że masz dwie zupełnie różne funkcje, które są opakowane w jedną w niezręczny sposób. Na przykład:

    public void Write(bool toOptical);
    

    Naprawdę powinny to być dwie metody

    public void WriteOptical();
    public void WriteMagnetic();
    

    ponieważ kod w nich może być zupełnie inny; być może będą musieli wykonywać różnego rodzaju obsługę błędów i sprawdzanie poprawności, a może nawet będą musieli inaczej formatować dane wychodzące. Nie możesz tego stwierdzić po prostu używając Write()lub nawet Write(Enum.Optical)(chociaż oczywiście możesz mieć jedną z tych metod, po prostu wywołaj metody wewnętrzne WriteOptical / Mag, jeśli chcesz).

Myślę, że to zależy. Nie robiłbym z tego zbyt wielkiego interesu poza numerem 1.

Sam Schutte
źródło
Bardzo dobre uwagi! Dwa parametry logiczne w jednej metodzie wyglądają naprawdę okropnie (chyba że masz szczęście, że masz nazwane parametry).
Yarik
Ta odpowiedź może jednak skorzystać na ponownym sformatowaniu! ;-)
Yarik
7

Wyliczenia są lepsze, ale nie nazwałbym parametrów logicznych jako „niedopuszczalne”. Czasami po prostu łatwiej jest dorzucić jedną małą wartość logiczną i przejść dalej (pomyśl o metodach prywatnych itp.)

Borek Bernard
źródło
po prostu uczyń metodę bardzo opisową, aby było jasne, co oznacza prawda lub tak.
simon,
6

Booleans może być OK w językach, które mają nazwane parametry, takich jak Python i Objective-C, ponieważ nazwa może wyjaśniać, co robi parametr:

file.writeData(data, overwrite=true)

lub:

[file writeData:data overwrite:YES]
Chris Lundie
źródło
1
IMHO, writeData () to zły przykład użycia parametru boolowskiego, niezależnie od tego, czy nazwane parametry są obsługiwane, czy nie. Bez względu na to, jak nazwiesz parametr, znaczenie wartości Fałsz nie jest oczywiste!
Yarik
4

Nie zgodziłbym się, że to dobra zasada . Oczywiście Enum tworzy w niektórych przypadkach lepszy jawny lub rozwlekły kod, ale z reguły wydaje się, że jest to zbyt daleko idące.

Najpierw weźmy twój przykład: odpowiedzialność (i zdolność) programistów do pisania dobrego kodu nie jest tak naprawdę zagrożona przez parametr boolowski. W twoim przykładzie programista mógłby napisać równie rozwlekły kod, pisząc:

dim append as boolean = true
file.writeData( data, append );

lub wolę bardziej ogólne

dim shouldAppend as boolean = true
file.writeData( data, shouldAppend );

Po drugie: przykład Enum, który podałeś, jest tylko „lepszy”, ponieważ przechodzisz przez CONST. Najprawdopodobniej w większości aplikacji przynajmniej niektóre, jeśli nie większość parametrów czasu, które są przekazywane do funkcji, to ZMIENNE. w takim przypadku mój drugi przykład (podawanie zmiennych o dobrych nazwach) jest znacznie lepszy, a Enum dałby ci niewielkie korzyści.

csmba
źródło
1
Chociaż zgadzam się, że parametry boolowskie są w wielu przypadkach akceptowalne, w przypadku tego przykładu writeData () parametr boolowski, taki jak shouldAppend, jest bardzo nieodpowiedni. Powód jest prosty: nie jest od razu oczywiste, co oznacza fałsz.
Yarik
4

Wyliczenia mają określoną korzyść, ale nie należy zastępować wszystkich wartości logicznych wyliczeniami. Jest wiele miejsc, w których prawda / fałsz jest właściwie najlepszym sposobem przedstawienia tego, co się dzieje.

Jednak używanie ich jako argumentów metod jest nieco podejrzane, po prostu dlatego, że nie możesz zobaczyć bez wnikania w to, co mają zrobić, ponieważ pozwalają ci zobaczyć, co tak naprawdę oznacza prawda / fałsz

Właściwości (szczególnie w przypadku inicjatorów obiektów C # 3) lub argumenty słów kluczowych (a la ruby ​​lub python) są znacznie lepszym sposobem, aby przejść tam, gdzie w przeciwnym razie użyłbyś argumentu boolowskiego.

Przykład w C #:

var worker = new BackgroundWorker { WorkerReportsProgress = true };

Przykład Rubiego

validates_presence_of :name, :allow_nil => true

Przykład Pythona

connect_to_database( persistent=true )

Jedyne, co przychodzi mi do głowy, gdzie argument metody boolowskiej jest właściwy, to java, gdzie nie ma ani właściwości, ani argumentów słów kluczowych. To jeden z powodów, dla których nienawidzę javy :-(

Orion Edwards
źródło
4

Chociaż prawdą jest, że w wielu przypadkach wyliczenia są bardziej czytelne i rozszerzalne niż wartości logiczne, absolutna reguła, że ​​„wartości logiczne są niedopuszczalne” jest głupia. Jest nieelastyczny i nieproduktywny - nie pozostawia miejsca na ludzką ocenę. Są podstawowym typem wbudowanym w większości języków, ponieważ są przydatne - rozważ zastosowanie go do innych typów wbudowanych: powiedzenie na przykład „nigdy nie używaj int jako parametru” byłoby po prostu szalone.

Ta zasada jest tylko kwestią stylu, a nie potencjalnych błędów lub wydajności w czasie wykonywania. Lepszą regułą byłoby „preferuj wyliczenia od wartości logicznych ze względu na czytelność”.

Spójrz na framework .Net. Wartości logiczne są używane jako parametry w wielu metodach. Interfejs .Net API nie jest doskonały, ale nie sądzę, aby użycie wartości logicznych jako parametrów było dużym problemem. Etykietka zawsze zawiera nazwę parametru i możesz również utworzyć tego rodzaju wskazówki - wypełnij swoje komentarze XML dotyczące parametrów metody, pojawią się one w etykiecie narzędzia.

Powinienem również dodać, że jest przypadek, kiedy powinieneś wyraźnie refaktoryzować wartości logiczne do wyliczenia - gdy masz dwie lub więcej wartości logicznych w swojej klasie lub w parametrach metody, a nie wszystkie stany są prawidłowe (np. Nie można ich mieć oba mają wartość true).

Na przykład, jeśli twoja klasa ma właściwości takie jak

public bool IsFoo
public bool IsBar

I błędem jest mieć oba z nich prawdziwe w tym samym czasie, tak naprawdę masz trzy ważne stany, lepiej wyrażone jako coś takiego:

enum FooBarType { IsFoo, IsBar, IsNeither };
Anthony
źródło
4

Niektóre zasady, których Twój kolega mógłby lepiej przestrzegać, to:

  • Nie bądź dogmatyczny w swoim projekcie.
  • Wybierz to, co najbardziej odpowiada użytkownikom Twojego kodu.
  • Nie próbuj wbijać kołków w kształcie gwiazdek w każdy otwór tylko dlatego, że podoba Ci się ten kształt w tym miesiącu!
Alex Worden
źródło
3

Wartość logiczna byłaby akceptowalna tylko wtedy, gdy nie zamierzasz rozszerzać funkcjonalności frameworka. Enum jest preferowane, ponieważ można rozszerzyć wyliczenie i nie przerywać poprzednich implementacji wywołania funkcji.

Inną zaletą Enum jest to, że jest łatwiejszy do odczytania.

David Basarab
źródło
2

Jeśli metoda zadaje pytanie takie jak:

KeepWritingData (DataAvailable());

gdzie

bool DataAvailable()
{
    return true; //data is ALWAYS available!
}

void KeepWritingData (bool keepGoing)
{
   if (keepGoing)
   {
       ...
   }
}

Wydaje się, że argumenty metod logicznych mają absolutnie doskonały sens.

Jesse C. Slicer
źródło
Któregoś dnia będziesz musiał dodać „pisz dalej, jeśli masz wolne miejsce”, a wtedy i tak przejdziesz od bool do enum.
Ilya Ryzhenkov
A potem będziesz miał znaczącą zmianę, przestarzałe przeciążenie lub może być coś takiego jak KeppWritingDataEx :)
Ilya Ryzhenkov
1
@Ilya, a może nie! Stworzenie możliwej sytuacji, w której obecnie żadna nie istnieje, nie neguje rozwiązania.
Jesse C. Slicer
1
Jesse ma rację. Planowanie takiej zmiany jest głupie. Rób to, co ma sens. W tym przypadku wartość logiczna jest zarówno intuicyjna, jak i przejrzysta. c2.com/xp/DoTheSimplestThingThatCouldPossablyWork.html
Derek Park
@Derek, w tym przypadku, wartość logiczna nie jest nawet potrzebna, ponieważ DataAvailable zawsze zwraca prawdę :)
Ilya Ryzhenkov
2

To zależy od metody. Jeśli metoda robi coś, co jest w oczywisty sposób prawdą / fałszem, to jest w porządku, np. Poniżej [choć nie mówię, że to najlepszy projekt dla tej metody, to tylko przykład, gdzie użycie jest oczywiste].

CommentService.SetApprovalStatus(commentId, false);

Jednak w większości przypadków, takich jak przykład, o którym wspominasz, lepiej jest użyć wyliczenia. W samym .NET Framework istnieje wiele przykładów, w których ta konwencja nie jest przestrzegana, ale dzieje się tak dlatego, że wytyczne projektowe zostały wprowadzone dość późno w cyklu.

Greg Beech
źródło
2

Sprawia to, że rzeczy są nieco bardziej wyraźne, ale zaczyna masowo rozszerzać złożoność twoich interfejsów - w czystym boolowskim wyborze, takim jak dołączanie / nadpisywanie, wydaje się to przesadą. Jeśli potrzebujesz dodać kolejną opcję (o której nie przychodzi mi do głowy w tym przypadku), zawsze możesz wykonać refaktor (w zależności od języka)

Jennifer
źródło
1
A co z prependingiem jako trzecią możliwą opcją? ;-))
Yarik
2

Wyliczenia z pewnością mogą uczynić kod bardziej czytelnym. Jest jeszcze kilka rzeczy, na które należy uważać (przynajmniej w .net)

Ponieważ podstawową pamięcią wyliczenia jest int, domyślną wartością będzie zero, więc należy upewnić się, że 0 jest rozsądną wartością domyślną. (Na przykład struktury mają wszystkie pola ustawione na zero podczas tworzenia, więc nie ma możliwości określenia wartości domyślnej innej niż 0. Jeśli nie masz wartości 0, nie możesz nawet przetestować wyliczenia bez rzutowania na int, co byłoby zły styl.)

Jeśli twoje wyliczenia są prywatne dla twojego kodu (nigdy nie są ujawniane publicznie), możesz przestać czytać tutaj.

Jeśli wyliczenia są publikowane w jakikolwiek sposób w kodzie zewnętrznym i / lub są zapisywane poza programem, rozważ ich jawne numerowanie. Kompilator automatycznie numeruje je od 0, ale jeśli zmienisz układ wyliczeń bez podawania im wartości, możesz skończyć z defektami.

Potrafię legalnie pisać

WriteMode illegalButWorks = (WriteMode)1000000;
file.Write( data, illegalButWorks );

Aby temu zaradzić, każdy kod, który używa wyliczenia, którego nie można być pewnym (np. Publiczne API), musi sprawdzić, czy wyliczenie jest prawidłowe. Robisz to przez

if (!Enum.IsDefined(typeof(WriteMode), userValue))
    throw new ArgumentException("userValue");

Jedynym zastrzeżeniem Enum.IsDefinedjest to, że wykorzystuje odbicie i jest wolniejsze. Występuje również problem z wersjonowaniem. Jeśli chcesz często sprawdzać wartość wyliczenia, lepiej będzie wykonać następujące czynności:

public static bool CheckWriteModeEnumValue(WriteMode writeMode)
{
  switch( writeMode )
  {
    case WriteMode.Append:
    case WriteMode.OverWrite:
      break;
    default:
      Debug.Assert(false, "The WriteMode '" + writeMode + "' is not valid.");
      return false;
  }
  return true;
}

Problem z wersjonowaniem polega na tym, że stary kod może wiedzieć, jak obsłużyć tylko 2 wyliczenia, które masz. Jeśli dodasz trzecią wartość, Enum.IsDefined będzie prawdziwe, ale stary kod niekoniecznie może to obsłużyć. Ups.

Jeszcze więcej zabawy można zrobić z [Flags]wyliczeniami, a kod weryfikacyjny do tego jest nieco inny.

Ja też pamiętać, że do przenoszenia, należy użyć połączenia ToString()na wyliczenia i korzystanie Enum.Parse()podczas czytania ich z powrotem w obu. ToString()I Enum.Parse()może obsługiwać [Flags]enum jest tak dobrze, więc nie ma powodu, aby nie z nich korzystać. Pamiętaj, że to kolejna pułapka, ponieważ teraz nie możesz nawet zmienić nazwy wyliczenia bez możliwego złamania kodu.

Więc czasami musisz zważyć wszystkie powyższe, kiedy zadajesz sobie pytanie Czy mogę uciec tylko z boolem?

Robert Paulson
źródło
1

IMHO wygląda na to, że wyliczenie byłoby oczywistym wyborem w każdej sytuacji, w której możliwe są więcej niż dwie opcje. Ale zdecydowanie SĄ sytuacje, w których potrzebujesz tylko wartości logicznej. W takim przypadku powiedziałbym, że użycie wyliczenia, w którym działa bool, byłoby przykładem użycia 7 słów, gdy wystarczy 4.

Jurassic_C
źródło
0

Wartości logiczne mają sens, gdy masz oczywisty przełącznik, który może być tylko jedną z dwóch rzeczy (tj. Stan żarówki, włączony lub wyłączony). Poza tym dobrze jest napisać to w taki sposób, aby było oczywiste, co przekazujesz - np. Zapisy na dysku - niebuforowane, buforowane wierszowo lub synchroniczne - powinno być przekazane jako takie. Nawet jeśli nie chcesz teraz zezwalać na zapisy synchroniczne (a więc jesteś ograniczony do dwóch opcji), warto rozważyć uczynienie ich bardziej szczegółowymi, aby wiedzieć, co robią na pierwszy rzut oka.

To powiedziawszy, możesz również użyć False i True (boolean 0 i 1), a następnie, jeśli potrzebujesz więcej wartości później, rozszerz funkcję, aby obsługiwać wartości zdefiniowane przez użytkownika (powiedzmy 2 i 3) oraz stare wartości 0/1 będzie ładnie się przenosić, więc Twój kod nie powinien się zepsuć.

Dan Udey
źródło
0

Czasami po prostu łatwiej jest modelować inne zachowanie z przeciążeniami. Kontynuując z twojego przykładu, wyglądałoby tak:

file.appendData( data );  
file.overwriteData( data );

To podejście pogarsza się, jeśli masz wiele parametrów, z których każdy pozwala na ustalony zestaw opcji. Na przykład metoda, która otwiera plik może mieć kilka permutacji trybu pliku (otwórz / utwórz), dostępu do pliku (odczyt / zapis), tryb współdzielenia (brak / odczyt / zapis). Całkowita liczba konfiguracji jest równa iloczynom kartezjańskim poszczególnych opcji. Oczywiście w takich przypadkach wielokrotne przeciążenia nie są właściwe.

Wyliczenia mogą, w niektórych przypadkach, uczynić kod bardziej czytelnym, chociaż sprawdzanie poprawności dokładnej wartości wyliczenia w niektórych językach (na przykład C #) może być trudne.

Często parametr boolowski jest dołączany do listy parametrów jako nowe przeciążenie. Jednym z przykładów w .NET jest:

Enum.Parse(str);  
Enum.Parse(str, true); // ignore case

To drugie przeciążenie stało się dostępne w nowszej wersji platformy .NET niż pierwsza.

Jeśli wiesz, że będą tylko dwie możliwości, wartość logiczna może być w porządku. Wyliczenia są rozszerzalne w sposób, który nie zepsuje starego kodu, chociaż stare biblioteki mogą nie obsługiwać nowych wartości wyliczeniowych, więc nie można całkowicie zignorować wersji.


EDYTOWAĆ

W nowszych wersjach języka C # można używać nazwanych argumentów, które IMO mogą sprawić, że wywołanie kodu będzie wyraźniejsze w taki sam sposób, jak wyliczenia. Korzystając z tego samego przykładu co powyżej:

Enum.Parse(str, ignoreCase: true);
Drew Noakes
źródło
0

Tam, gdzie zgadzam się, że wyliczenia są dobrym rozwiązaniem, w metodach, w których masz 2 opcje (i tylko dwie opcje możesz mieć czytelność bez wyliczenia).

na przykład

public void writeData(Stream data, boolean is_overwrite)

Uwielbiam Enum, ale wartości logiczne też są przydatne.

Haris Krajina
źródło
0

To jest późny wpis w starym poście i jest tak daleko w dół strony, że nikt go nigdy nie przeczyta, ale ponieważ nikt już tego nie powiedział ....

Komentarz w tekście znacznie ułatwia rozwiązanie nieoczekiwanego boolproblemu. Oryginalny przykład jest szczególnie ohydny: wyobraź sobie, że próbujesz nazwać zmienną w deklaracji funkcji! To byłoby coś takiego

void writeData( DataObject data, bool use_append_mode );

Ale dla przykładu, powiedzmy, że to jest deklaracja. Następnie, dla niewyjaśnionego inaczej argumentu logicznego, umieściłem nazwę zmiennej w komentarzu w wierszu. Porównać

file.writeData( data, true );

z

file.writeData( data, true /* use_append_mode */);
Robert Martin
źródło
-1

To naprawdę zależy od dokładnej natury argumentu. Jeśli nie jest to tak / nie lub prawda / fałsz, to wyliczenie czyni go bardziej czytelnym. Ale w przypadku wyliczenia musisz sprawdzić argument lub mieć akceptowalne domyślne zachowanie, ponieważ można przekazać niezdefiniowane wartości typu podstawowego.

CheeZe5
źródło
-1

Użycie w przykładzie wyliczeń zamiast wartości logicznych pomaga uczynić wywołanie metody bardziej czytelną. Jednak jest to substytut mojego ulubionego elementu życzeń w C #, nazwanych argumentów w wywołaniach metod. Ta składnia:

var v = CallMethod(pData = data, pFileMode = WriteMode, pIsDirty = true);

byłby doskonale czytelny i można by wtedy zrobić to, co powinien zrobić programista, czyli wybrać najbardziej odpowiedni typ dla każdego parametru w metodzie, bez względu na to, jak wygląda w IDE.

C # 3.0 zezwala na nazwane argumenty w konstruktorach. Nie wiem, dlaczego nie mogą tego zrobić również metodami.

MusiGenesis
źródło
Ciekawy pomysł. Ale czy byłbyś w stanie zmienić kolejność parametrów? Pominąć parametry? Skąd kompilator wiedziałby, do którego przeciążenia byłeś przypisany, gdyby było to opcjonalne? Czy musiałbyś także nazwać wszystkie parametry na liście?
Drew Noakes
-1

Tylko wartości logiczne true/ false. Nie jest więc jasne, co to oznacza. Enummoże mieć znaczącą nazwę, na przykład OVERWRITE, APPENDitd enums tak są lepsze.

fastcodejava
źródło