Jaka jest różnica między And i AndAlso w VB.NET?

250

W VB.NET, jaka jest różnica między Andi AndAlso? Z którego powinienem korzystać?

Nakul Chaudhary
źródło

Odpowiedzi:

380

AndOperator ocenia obu stron, w którym AndAlsoocenia się po prawej stronie tylko wtedy, gdy lewa strona jest prawdą.

Przykład:

If mystring IsNot Nothing And mystring.Contains("Foo") Then
  ' bla bla
End If

Powyższe zgłasza wyjątek, jeśli mystring = Nothing

If mystring IsNot Nothing AndAlso mystring.Contains("Foo") Then
  ' bla bla
End If

Ten nie rzuca wyjątku.

Więc jeśli pochodzisz ze świata C #, powinieneś używać AndAlsotak, jak chcesz &&.

Więcej informacji tutaj: http://www.panopticoncentral.net/2003/08/18/the-ballad-of-andalso-and-orelse/

Nico
źródło
2
Link „Więcej informacji” jest uszkodzony. Oto nowy adres URL: panopticoncentral.net/2003/08/18/…
Rory O'Kane
12
Czy ktoś wie, dlaczego zamiast tego nie wybrał „AndThen”? Myślę, że byłoby to bardziej intuicyjne.
potężny
7
Zawsze myślałem, że to sprzeczne z intuicją. A także sugerowałoby, że sprawdzi oba i powinno być na odwrót! Dlatego muszę przyjść do SO, aby sprawdzić takie rzeczy (tak, jestem facetem). Nigdy nie powinieneś także zadawać pytań typu „różnica między And i Andsoo”. Za dużo ands! Mój nauczyciel języka angielskiego by mnie zabił
Robin French
3
Za każdym razem, gdy korzystam z OrElse, zawsze myślę o South Park „Albo co innego?” „Dokładnie”
Robin French
1
@ potężne zgadywanie, że spowodowałoby to więcej zamieszania, ponieważ Thenjest to jego własne słowo kluczowe.
binki,
29

AndOperator sprawdzi wszystkie warunki w sprawozdaniu przed kontynuowaniem, natomiast operator AndAlso zatrzyma, jeśli wie, że warunek jest fałszywy. Na przykład:

if x = 5 And y = 7

Sprawdza, czy x jest równe 5, a jeśli y jest równe 7, a następnie kontynuuje, jeśli oba są prawdziwe.

if x = 5 AndAlso y = 7

Sprawdza, czy x jest równe 5. Jeśli nie, nie sprawdza, czy y wynosi 7, ponieważ wie, że warunek jest już fałszywy. (Nazywa się to zwarciem.)

Zasadniczo ludzie używają metody zwarcia, jeśli istnieje powód, aby wyraźnie nie sprawdzać drugiej części, jeśli pierwsza część nie jest prawdziwa, na przykład, gdyby w przypadku sprawdzenia sprawdziłaby wyjątek. Na przykład:

If Not Object Is Nothing AndAlso Object.Load()

Jeśli użyłby tego Andzamiast AndAlso, nadal próbowałby, Object.Load()nawet gdyby tak było nothing, co spowodowałoby wyjątek.

Ed Marty
źródło
14
Jeśli prawa strona ma efekt uboczny, którego potrzebujesz, po prostu przenieś go na lewą stronę zamiast używać „I”. Naprawdę potrzebujesz „I”, jeśli obie strony mają skutki uboczne. A jeśli masz tak wiele efektów ubocznych, prawdopodobnie robisz coś innego źle.
Joel Coehoorn,
1
Po pierwsze, Andalso nie jest przede wszystkim używane do „oszczędzania czasu pracy”, co jest niedorzeczne. Po drugie, wykonanie drugiego argumentu pożytecznego „efektu ubocznego” jest brzydką złą praktyką.
Tor Haugen,
2
Nie można jednak argumentować, że nie „oszczędza czasu działania”. I znalazłem sytuacje, w których skutki uboczne są w rzeczywistości nie brzydką dupą.
Ed Marty,
1
„Zasadniczo ludzie używają metody zwarcia, jeśli istnieje powód, aby wyraźnie nie sprawdzać drugiej części” Eee, wut? Mam nadzieję, że ludzie używają zwarć, chyba że mają ku temu powód! Nikt nie powinien korzystać ze starego and/ orchyba, że ​​ma powód - z którego uważam, że uzasadnionych jest niewiele i jest daleko od siebie. Z pewnością jest powód, dla którego większość innych języków domyślnie zwiera: zachowuje sens wyniku, nie oceniając potencjalnie kosztownych wyrażeń, gdy nic nie wnoszą. Ukrywanie efektów ubocznych w warunkach powinno być, no cóż, bocznymi oczami. Ale to tylko moja opinia ...
underscore_d
20

Co ciekawe żadna z odpowiedzi nie wspomniano, że Andi Orw VB.NET są operatory bitowe podczas gdy OrElsei AndAlsosą ściśle operatorów logicznych.

Dim a = 3 OR 5 ' Will set a to the value 7, 011 or 101 = 111
Dim a = 3 And 5 ' Will set a to the value 1, 011 and 101 = 001
Dim b = 3 OrElse 5 ' Will set b to the value true and not evaluate the 5
Dim b = 3 AndAlso 5 ' Will set b to the value true after evaluating the 5
Dim c = 0 AndAlso 5 ' Will set c to the value false and not evaluate the 5

Uwaga : rozważana jest niezerowa liczba całkowita true; Dim e = not 0zestaw edo -1demonstracji Notjest również operatorem bitowym.

||i &&(C # wersji OrElsea AndAlso) zwracają ostatni z wyrażenia który byłby 3i 5odpowiednio. Pozwala to użyć idiomu v || 5w języku C #, aby podać 5jako wartość wyrażenia, gdy vjest nulllub ( 0i liczbę całkowitą), a także wartość w vprzeciwnym razie. Różnica w semantyce może zaskoczyć programistę C # w VB.NET, ponieważ ten „idiom wartości domyślnej” nie działa w VB.NET.

Tak więc, aby odpowiedzieć na pytanie : Użyj Ori Anddo operacji bitowych (liczba całkowita lub wartość logiczna). Użyj OrElsei AndAlso„zewrzyj” operację, aby zaoszczędzić czas, lub przetestuj ważność oceny przed jej oceną. If valid(evaluation) andalso evaluation thenlubif not (unsafe(evaluation) orelse (not evaluation)) then

Bonus: Jaka jest wartość następujących rzeczy?

Dim e = Not 0 And 3
Charles Jacks
źródło
Myślę, że mylić ||i &&z ??. Podczas gdy istnieją języki, w których ||zwracana jest wartość non-falsey, C # nie jest jednym z nich i zwraca a bool(z wyjątkiem podniesionych operatorów zerowalnych, w których można uzyskać Nullable<bool>wynik)
Ben Voigt
14
If Bool1 And Bool2 Then

Ocenia zarówno Bool1, jak i Bool2

If Bool1 AndAlso Bool2 Then

Ocenia Bool2 wtedy i tylko wtedy, gdy Bool1 jest prawdziwy.

Bryan Anderson
źródło
13

Tylko dla wszystkich tych, którzy twierdzą, że skutki uboczne są złe: miejscem, w którym dobre są dwa skutki uboczne w jednym stanie, czytałoby się dwa obiekty pliku w tandemie.

While File1.Seek_Next_Row() And File2.Seek_Next_Row()
    Str1 = File1.GetRow()
    Str2 = File2.GetRow()
End While

Użycie polecenia Andgwarantuje, że wiersz jest zużywany za każdym razem, gdy sprawdzany jest warunek. Natomiast AndAlsomoże odczytać ostatni wiersz File1i wyjść File2bez zużytej linii.

Oczywiście powyższy kod nie działałby, ale ciągle używam takich efektów ubocznych i nie uważam go za kod „ zły ” lub „ zły ”, jak niektórzy moglibyście w to uwierzyć. Jest łatwy do odczytania i wydajny.

Ian
źródło
5

Prostym sposobem na przemyślenie tego jest użycie prostszego języka angielskiego

If Bool1 And Bool2 Then
If [both are true] Then


If Bool1 AndAlso Bool2 Then
If [first is true then evaluate the second] Then
rbrill
źródło
3
Angielski jest bardziej mylący niż kod, ponieważ nie ma specyfikacji!
binki,
5

AndAlso jest bardzo podobny do And, z tym wyjątkiem, że działa jak && w C #, C ++ itp.

Różnica polega na tym, że jeśli pierwsza klauzula (przed AndAlso) jest prawdziwa, druga klauzula nigdy nie jest oceniana - złożone wyrażenie logiczne jest „zwarte”.

Jest to czasami bardzo przydatne, np. W wyrażeniu takim jak:

If Not IsNull(myObj) AndAlso myObj.SomeProperty = 3 Then
   ...
End If

Użycie starego wyrażenia „I” w powyższym wyrażeniu spowodowałoby wygenerowanie wyjątku NullReferenceException, gdyby myObj miały wartość NULL.

Tor Haugen
źródło
5

Zobacz także pytanie Przepełnienie stosu: czy zawsze powinienem używać operatorów AndAlso i OrElse? .

Ponadto: komentarz dla tych, którzy wspominali o używaniu, Andjeśli prawa strona wyrażenia ma efekt uboczny, którego potrzebujesz:

Jeśli prawa strona ma efekt uboczny, którego potrzebujesz, po prostu przenieś go na lewą stronę zamiast używać „I”. Naprawdę potrzebujesz „I”, jeśli obie strony mają skutki uboczne. A jeśli masz tak wiele efektów ubocznych, prawdopodobnie robisz coś innego źle. Ogólnie rzecz biorąc, naprawdę powinieneś preferować AndAlso.

Joel Coehoorn
źródło
3

Oprócz powyższych odpowiedzi AndAlso zapewnia proces warunkowania zwany zwarciem. Wiele języków programowania ma tę funkcjonalność wbudowaną, podobnie jak vb.net, i może zapewnić znaczny wzrost wydajności w długich instrukcjach warunkowych, eliminując niepotrzebne oceny.

Innym podobnym warunkiem jest warunek OrElse, który sprawdzałby poprawny warunek tylko wtedy, gdy lewy warunek jest fałszywy, co eliminuje niepotrzebne sprawdzanie warunku po znalezieniu warunku prawdziwego.

Radziłbym, abyś zawsze stosował procesy zwarciowe i ustrukturyzował swoje instrukcje warunkowe w taki sposób, aby przynieść największe korzyści. Na przykład najpierw przetestuj swoje najbardziej wydajne i najszybsze warunki, aby biegać w długich warunkach tylko wtedy, gdy jest to absolutnie konieczne, a za drugim razem zwarcie.

davidallyoung
źródło
Warto również wspomnieć o IIF (Immediate If), ponieważ nie powoduje zwarcia i może tworzyć warunki zupełnie odmienne od intencji programisty, ponieważ oceniane są zarówno komponenty prawda, jak i fałsz. Wcześniej ktoś stwierdził, że używa tego zachowania niepożądanego celowo, ale - nie uważam tego za skuteczną metodę, ponieważ Natychmiastowe If nie ma celowego celu przeprowadzenia oceny w sposób, który mogę wykryć.
jinzai
„Oprócz powyższych odpowiedzi AndAlso zapewnia proces warunkowania zwany zwarciem”. Każda odpowiedź powyżej tego dotyczy zwarcia. : P Ale dobry opis i rekomendacje.
underscore_d
1

Dla większości z nas OrElse i AndAlso wykonają tę sztuczkę, z wyjątkiem kilku mylących wyjątków (mniej niż 1%, w których możemy użyć Or i And).

Staraj się nie dać się ponieść emocjom ludzi popisujących się logiką logiczną i sprawiających, że wygląda jak rakieta.

Jest to dość proste i proste, a czasami twój system może nie działać zgodnie z oczekiwaniami, ponieważ nie podoba ci się twoja logika. A przecież twój mózg mówi ci, że jego logika jest w 100% przetestowana i sprawdzona i powinna działać. W tym momencie przestań ufać swojemu mózgowi i poproś go, aby pomyślał ponownie lub (nie OrElse, a może OrElse) zmusisz się do szukania innej pracy, która nie wymaga wiele logiki.

Anand
źródło
0

Aby zrozumieć słowami, a nie kodami:

Przypadek użycia:
Za pomocą „I” kompilator sprawdzi wszystkie warunki, więc jeśli sprawdzasz, czy obiekt może być „Nic”, a następnie sprawdzasz jedną z jego właściwości, wystąpi błąd wykonania.
Ale z AndAlso z pierwszym „fałszem” w warunkach będzie sprawdzał następny, więc nie wystąpi błąd.

Bazylia
źródło