Będę niepopularny i powiem tak, to zła praktyka. JEŻELI funkcjonalność kodu polega na nim w celu wdrożenia logiki warunkowej.
to znaczy
if(quickLogicA && slowLogicB) {doSomething();}
jest dobrze, ale
if(logicA && doSomething()) {andAlsoDoSomethingElse();}
jest zły i na pewno nikt się z nim nie zgodzi ?!
if(doSomething() || somethingElseIfItFailed() && anotherThingIfEitherWorked() & andAlwaysThisThing())
{/* do nothing */}
Uzasadnienie:
Błędy w kodzie, jeśli obie strony są oceniane, zamiast po prostu nie wykonywać logiki. Argumentowano, że nie jest to problem, operator „i” jest zdefiniowany w języku c #, więc znaczenie jest jasne. Uważam jednak, że to nieprawda.
Powód 1. Historyczny
Zasadniczo polegasz na (jak pierwotnie zamierzano) optymalizacji kompilatora, aby zapewnić funkcjonalność swojego kodu.
Chociaż w c # specyfikacja języka gwarantuje, że operator logiczny i operator zwarły. Nie dotyczy to wszystkich języków i kompilatorów.
wikipeda wymienia różne języki i ich zwarcia http://en.wikipedia.org/wiki/Short-circuit_evaluation, ponieważ istnieje wiele sposobów. I kilka dodatkowych problemów, o których tu nie mówię.
W szczególności FORTRAN, Pascal i Delphi mają flagi kompilatora, które przełączają to zachowanie.
Dlatego: może się okazać, że kod działa podczas kompilacji do wydania, ale nie do debugowania lub z alternatywnym kompilatorem itp.
Powód 2. Różnice językowe
Jak widać z wikipedii, nie wszystkie języki mają takie samo podejście do zwarć, nawet jeśli określają, w jaki sposób operatorzy logiczni powinni sobie z tym poradzić.
W szczególności operator „i” VB.Net nie powoduje zwarcia, a TSQL ma pewne cechy szczególne.
Biorąc pod uwagę, że współczesne „rozwiązanie” może zawierać wiele języków, takich jak javascript, regex, xpath itp., Powinieneś wziąć to pod uwagę, wyjaśniając funkcjonalność kodu.
Powód 3. Różnice w języku
Na przykład wstawka VB jeśli zachowuje się inaczej niż jej. Ponownie we współczesnych aplikacjach Twój kod może się przemieszczać, na przykład kod z tyłu i wbudowany formularz internetowy, musisz zdawać sobie sprawę z różnic w znaczeniu.
Powód 4. Twój konkretny przykład zerowania sprawdzania parametru funkcji
To bardzo dobry przykład. Jest to coś, co wszyscy robią, ale w rzeczywistości jest to zła praktyka, gdy się nad tym zastanowić.
Tego rodzaju sprawdzanie jest bardzo częste, ponieważ znacznie zmniejsza liczbę linii kodu. Wątpię, by ktokolwiek przywołał to w recenzji kodu. (i oczywiście z komentarzy i ocen widać, że jest popularny!)
Jednak zawodzi najlepsza praktyka z więcej niż jednego powodu!
Jego bardzo jasne z wielu źródeł, że najlepszym rozwiązaniem jest, aby sprawdzić parametry dla ważności przed ich użyciem i rzucić wyjątek, jeśli są one nieważne. Fragment kodu nie pokazuje otaczającego kodu, ale prawdopodobnie powinieneś robić coś takiego:
if (smartphone == null)
{
//throw an exception
}
// perform functionality
Dzwonisz funkcję z wewnątrz rachunku warunkowego. Chociaż nazwa Twojej funkcji sugeruje, że po prostu oblicza wartość, może ukrywać skutki uboczne. na przykład
Smartphone.GetSignal() { this.signal++; return this.signal; }
else if (smartphone.GetSignal() < 1)
{
// Do stuff
}
else if (smartphone.GetSignal() < 2)
{
// Do stuff
}
najlepsza praktyka sugeruje:
var s = smartphone.GetSignal();
if(s < 50)
{
//do something
}
Jeśli zastosujesz te najlepsze praktyki do swojego kodu, zobaczysz, że Twoja szansa na uzyskanie krótszego kodu poprzez użycie ukrytego warunkowego znika. Najlepszą praktyką jest zrobienie czegoś , załatwienie sprawy, w której smartfon jest zerowy.
Myślę, że przekonasz się, że dotyczy to również innych powszechnych zastosowań. Musisz pamiętać, że mamy również:
warunkowe inline
var s = smartphone!=null ? smartphone.GetSignal() : 0;
i zerowa koalescencja
var s = smartphoneConnectionStatus ?? "No Connection";
które zapewniają podobną funkcjonalność krótkiego kodu z większą przejrzystością
liczne linki do poparcia wszystkich moich punktów:
https://stackoverflow.com/questions/1158614/what-is-the-best-practice-in-case-one-argument-is-null
Sprawdzanie poprawności parametrów konstruktora w C # - Najlepsze praktyki
Czy należy sprawdzić wartość zerową, jeśli nie spodziewa się wartości zerowej?
https://msdn.microsoft.com/en-us/library/seyhszts%28v=vs.110%29.aspx
https://stackoverflow.com/questions/1445867/why-would-a-language-not-use-short-circuit-evaluation
http://orcharddojo.net/orchard-resources/Library/DevelopmentGuidelines/BestPractices/CSharp
przykłady flag kompilatora wpływających na zwarcie:
Fortran: "sce | nosce Domyślnie kompilator dokonuje oceny zwarcia w wybranych wyrażeniach logicznych przy użyciu reguł XL Fortran. Określenie sce pozwala kompilatorowi używać reguł innych niż XL Fortran. Kompilator przeprowadzi ocenę zwarcia, jeśli pozwalają na to obecne reguły . Domyślnie jest nosce. ”
Pascal: „B - Flaga flagowa, która kontroluje ocenę zwarcia. Aby uzyskać więcej informacji na temat oceny zwarć, zobacz Kolejność oceny operandów operatorów diadycznych. Aby uzyskać więcej informacji, zobacz także opcję kompilatora -sc ( udokumentowane w Podręczniku użytkownika). ”
Delphi: „Delphi domyślnie obsługuje analizę zwarć. Można ją wyłączyć za pomocą dyrektywy kompilatora {$ BOOLEVAL OFF}.”