Comanda logică și compilatorul C #

În C#, (și nu ezitați să răspundeți pentru alte limbi), ce ordine are timpul de execuție să evalueze o declarație logică?

Exemplu:

DataTable myDt = new DataTable();
if (myDt != null && myDt.Rows.Count > 0)
{
    //do some stuff with myDt
}

Ce declarație evaluează runtime-ul -

myDt != null

sau:

myDt.Rows.Count > 0

?

Există o vreme când compilatorul ar evalua declarația înapoi? Poate când este implicat un operator "OR"?


& is known as a logical bitwise operator and will always evaluate all the sub-expressions

Ce este un exemplu bun când să folosiți operatorul bitwise în loc de "booleanul scurtcircuitat"?

0
fr hi bn

18 răspunsuri

Îmi plac răspunsurile lui Orion. Voi adăuga două lucruri:

  1. Aplicațiile de la stânga la dreapta se aplică în continuare mai întâi
  2. Înăuntru-exterior pentru a se asigura că toate argumentele sunt rezolvate înainte de a apela funcția

Spuneți că avem următorul exemplu:

a = Foo(5, GetSummary("Orion", GetAddress("Orion")),
           GetSummary("Chris", GetAddress("Chris")));

Iată ordinea de execuție:

  1. GetAddress("Orion")
  2. GetSummary("Orion", ...)
  3. GetAddress("Chris")
  4. GetSummary("Chris", ...)
  5. Foo(...)
  6. Assigns to a

Nu pot sa vorbesc despre cerintele legale ale C# (desi am testa un exemplu similar folosind Mono inainte de a scrie acest post), dar aceasta ordine este garantata in Java.

And just for completeness (since this is a language-agnostic thread as well), there are languages like C and C++, where the order is not guaranteed unless there is a sequence point. References: 1, 2. In answering the thread's question, however, && and || are sequence points in C++ (unless overloaded; also see OJ's excellent answer). So some examples:

  • foo() && bar()
  • foo() & bar()

In the && case, foo() is guaranteed to run before bar() (if the latter is run at all), since && is a sequence point. In the & case, no such guarantee is made (in C and C++), and indeed bar() can run before foo(), or vice versa.

0
adăugat

Stânga, apoi se oprește dacă este nulă.

Editați: În vb.net va evalua ambele și va arunca o eroare, dacă nu utilizați AndAlso

0
adăugat

Unele limbi au situații interesante în care expresiile sunt executate într-o ordine diferită. Mă gândesc în mod special la Ruby, dar sunt sigur că l-au împrumutat de la altă parte (probabil Perl).

Expresiile din logica vor rămâne de la stânga la dreapta, dar de exemplu:

puts message unless message.nil?

Cele de mai sus vor evalua "message.nil?" în primul rând, dacă evaluează false (cu excepția cazului în care se execută atunci când condiția este falsă în loc de adevărată), se va executa mesajul "puts message", care imprimă conținutul variabilei mesajului pe ecran.

Este un fel de mod interesant de a vă structura codul uneori ... Îmi place personal să îl folosesc pentru linii foarte scurte ca cele de mai sus.

Editați | ×:

Pentru a face ceva mai clară, cele de mai sus sunt aceleași cu:

unless message.nil?
  puts message
end
0
adăugat

@shsteimer

Conceptul de modestă se referă la supraîncărcarea operatorului. în declarația:   ...   A este evaluat mai întâi, dacă este evaluat la fals, B nu este niciodată evaluat. Același lucru este valabil și pentru

Nu este supraîncărcarea operatorului. Supraîncărcarea operatorului este termenul dat pentru a vă permite să definiți comportamentul personalizat pentru operatori, cum ar fi *, +, = și așa mai departe.

Acest lucru vă va permite să vă scrieți propria clasă "Log" și apoi să o faceți

a = new Log(); // Log class overloads the + operator
a + "some string"; // Call the overloaded method - otherwise this wouldn't work because you can't normally add strings to objects.

Fac asta

a() || b() // be never runs if a is true

is actually called Short Circuit Evaluation

0
adăugat

Când lucrurile sunt toate în linie, sunt executate de la stânga la dreapta.

Atunci când lucrurile sunt imbricate, ele sunt executate de la interior la exterior. Acest lucru poate părea confuz, așa cum de obicei ceea ce este "cel mai lăuntru" este pe partea dreaptă a liniei, așa că pare că merge înapoi ...

De exemplu

a = Foo( 5, GetSummary( "Orion", GetAddress("Orion") ) );

Lucrurile se întâmplă astfel:

  • Call GetAddress with the literal "Orion"
  • Call GetSummary with the literal "Orion" and the result of GetAddress
  • Call Foo with the literal 5 and the result of GetSummary
  • Assign this value to a
0
adăugat

Conceptul de modestă se referă la supraîncărcarea operatorului. în declarația:

if( A && B){
    // do something
}

A este evaluat mai întâi, dacă este evaluat la fals, B nu este niciodată evaluat. Același lucru este valabil și pentru

if(A || B){
    //do something
}

A este evaluat mai întâi, dacă evaluarea este adevărată, B nu este niciodată evaluată.

Acest concept, supraîncărcare, se aplică (cred) tuturor limbajelor stilului C, precum și multor altele.

0
adăugat

vb.net

if( x isNot Nothing AndAlso x.go()) then
  1. Evaluation is done left to right
  2. AndAlso operator makes sure that only if the left side was TRUE, the right side will be evaluated (very important, since ifx is nothing x.go will crash)

Puteți folosi Și în loc deAndAlso în vb. caz în care partea stângă este evaluată mai întâi, dar partea dreaptă va fi evaluată indiferent de rezultat.

Bune practici: Utilizați întotdeauna și în plus, cu excepția cazului în care aveți un motiv foarte bun de ce nu.


It was asked in a followup why or when would anyone use And instead of AndAlso (or & instead of &&): Here is an example:

if ( x.init() And y.init()) then
   x.process(y)
end 
y.doDance()

În acest caz, vreau să init atât X și Y. Y trebuie inițializat pentru ca y.DoDance să poată executa. Cu toate acestea, în funcția init() fac și alte lucruri, cum ar fi verificarea unei socket-uri și numai dacă funcționează bine, pentru ambele , ar trebui să merg și să fac x.process (y).

Din nou, probabil că acest lucru nu este necesar și nu este elegant în 99% din cazuri, de aceea am spus că implicit ar trebui să fie folosirea AndAlso .

0
adăugat

Am auzit undeva că compilatorii lucrează înapoi, dar nu sunt sigur ce este adevărat.

0
adăugat

Care este un bun exemplu de când să utilizați operatorul bitwise în loc de "booleanul scurtcircuitat"?

Să presupunem că aveți steaguri, de exemplu pentru atributele de fișiere. Să presupunem că ați definit READ ca 4, WRITE ca 2 și EXEC ca 1. În binar, asta e:

READ  0100  
WRITE 0010  
EXEC  0001

Fiecare steag are un set de biți și fiecare este unic. Operatorii bitului vă permit să combinați aceste steaguri:

flags = READ & EXEC; // value of flags is 0101
0
adăugat

ZombieSheep is dead-on. The only "gotcha" that might be waiting is that this is only true if you are using the && operator. When using the & operator, both expressions will be evaluated every time, regardless if one or both evaluate to false.

if (amHungry & whiteCastleIsNearby)
{
   // The code will check if White Castle is nearby
   // even when I am not hungry
}

if (amHungry && whiteCastleIsNearby)
{
   // The code will only check if White Castle is nearby
   // when I am hungry
}
0
adăugat

Nopes, at least the C# compiler doesn't work backwards (in either && or ||). It's left to right.

0
adăugat

C #: de la stânga la dreapta, iar procesarea se oprește dacă se găsește un non-match (evaluat la false).

0
adăugat
După cum au afirmat și alții, scurtcircuitarea pe && operatorul are loc pe false .
adăugat autor Broam, sursa

The D programming language Does do left-to-right evaluation with short circuiting and doesn't allow overloading of the && and '||' operators.

0
adăugat

You use & when you specifically want to evaluate all the sub-expressions, most likely because they have side-effects you want, even though the final result will be false and thus not execute your then part of your if-statement.

Note that & and | operates for both bitwise masks and boolean values and is not just for bitwise operations. They're called bitwise, but they are defined for both integers and boolean data types in C#.

0
adăugat

Note that there is a difference between && and & regarding how much of your expression is evaluated.

&& is known as a short-circuited boolean AND, and will, as noted by others here, stop early if the result can be determined before all the sub-expressions are evaluated.

& is known as a logical bitwise operator and will always evaluate all the sub-expressions.

Ca atare:

if (a() && b())

Se va apela numai b dacă a returnează true .

cu toate acestea, aceasta:

if (a() & b())

Se va apela întotdeauna ambele a și b , chiar dacă rezultatul apelului a este fals și astfel este cunoscut false indiferent de rezultatul apelului b .

Aceeași diferență există și pentru || și | operatori.

0
adăugat

"C #: de la stânga la dreapta și prelucrarea se oprește dacă se găsește un meci (evaluat la adevărat)".

Oile de zombie sunt greșite, nu e suficient să le replici la vot.

The question is about the && operator, not the || operator.

In the case of && evaluation will stop if a FALSE is found.

În cazul lui || evaluarea se oprește dacă se găsește un TRUE.

0
adăugat
Da. Ai dreptate. Sper că răspunsul meu inițial a fost interpretat corect. Cu siguranță nu intenționam să induc în eroare pe nimeni.
adăugat autor ZombieSheep, sursa

@csmba:

It was asked in a followup why or when would anyone use And instead of AndAlso (or & instead of &&): Here is an example:

if ( x.init() And y.init()) then
   x.process(y)
end 
y.doDance()

In this case, I want to init both X and Y. Y must be initialized in order for y.DoDance to be able to execute. However, in the init() function I am doing also some extra thing like checking a socket is open, and only if that works out ok, for both, I should go ahead and do the x.process(y).

I believe this is rather confusing. Although your example works, it's not the typical case for using And (and I would probably write this differently to make it clearer). And (& in most other languages) is actually the bitwise-and operation. You would use it to calculate bit operations, for example deleting a flag bit or masking and testing flags:

Dim x As Formatting = Formatting.Bold Or Formatting.Italic
If (x And Formatting.Italic) = Formatting.Italic Then
    MsgBox("The text will be set in italic.")
End If
0
adăugat

Îmi dau seama că această întrebare a fost deja răspuns, dar aș vrea să arunc o altă informație care este legată de subiect.

In languages, like C++, where you can actually overload the behaviour of the && and || operators, it is highly recommended that you do not do this. This is because when you overload this behaviour, you end up forcing the evaluation of both sides of the operation. This does two things:

  1. Se rupe mecanismul de evaluare leneș, deoarece suprasarcina este o funcție care trebuie invocată și, prin urmare, ambii parametri sunt evaluați înainte de a apela funcția.
  2. Ordinea de evaluare a parametrilor menționați nu este garantată și poate fi specifică compilatorului. Prin urmare, obiectele nu s-ar comporta în același mod ca și în exemplele enumerate în răspunsul / întrebările anterioare.

Pentru mai multe informații, citiți cartea lui Scott Meyers, C ++ mai eficient . Noroc!

0
adăugat