Frage

In welcher Reihenfolge wertet die Laufzeit in C# (und Sie können gerne auch für andere Sprachen antworten) eine Logikanweisung aus?

Beispiel:

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

Welche Anweisung wertet die Laufzeit zuerst aus?

myDt != null

oder:

myDt.Rows.Count > 0

?

Gibt es eine Zeit, in der der Compiler die Anweisung jemals rückwärts auswerten würde?Vielleicht, wenn ein „OR“-Operator beteiligt ist?


& ist als logischer bitweiser Operator bekannt und wertet immer alle Unterausdrücke aus

Was ist ein gutes Beispiel dafür, wann der bitweise Operator anstelle des „kurzgeschlossenen Booleschen“ verwendet werden sollte?

War es hilfreich?

Lösung

C# :Von links nach rechts, und die Verarbeitung stoppt, wenn eine Nichtübereinstimmung (Auswertung als „falsch“) gefunden wird.

Andere Tipps

"C# :Von links nach rechts, und die Verarbeitung stoppt, wenn eine Übereinstimmung gefunden wird (die als wahr ausgewertet wird).

Das Zombie-Schaf hat Unrecht, es gibt nicht genug Repräsentanten, um es abzulehnen.

Die Frage bezieht sich auf den && Operator, nicht das || Operator.

Im Fall von && wird die Auswertung gestoppt, wenn ein FALSE gefunden wird.

Im Fall von || Die Bewertung stoppt, wenn ein True gefunden wird.

Mir ist klar, dass diese Frage bereits beantwortet wurde, aber ich möchte noch eine weitere Information hinzufügen, die mit dem Thema zusammenhängt.

In Sprachen wie C ++ können Sie das Verhalten der && und || tatsächlich überlasten können Betreiber, es wird dringend empfohlen, dass Sie mach das nicht.Denn wenn Sie dieses Verhalten überlasten, erzwingen Sie letztendlich die Auswertung beider Seiten des Vorgangs.Dies bewirkt zwei Dinge:

  1. Dadurch wird der verzögerte Auswertungsmechanismus unterbrochen, da es sich bei der Überladung um eine Funktion handelt, die aufgerufen werden muss, und daher beide Parameter vor dem Aufruf der Funktion ausgewertet werden.
  2. Die Reihenfolge der Auswertung dieser Parameter ist nicht garantiert und kann vom Compiler abhängig sein.Daher würden sich die Objekte nicht auf die gleiche Weise verhalten wie in den in der Frage/den vorherigen Antworten aufgeführten Beispielen.

Für weitere Informationen lesen Sie das Buch von Scott Meyers: Effektiveres C++.Prost!

vb.net

if( x isNot Nothing AndAlso x.go()) then
  1. Die Auswertung erfolgt von links nach rechts
  2. Und auch Der Operator stellt sicher, dass nur dann die rechte Seite ausgewertet wird, wenn die linke Seite WAHR war (sehr wichtig, da ifx nichts ist, wird x.go abstürzen)

Sie können verwenden Und stattAndAlso in vb.In diesem Fall wird auch die linke Seite zuerst ausgewertet, die rechte Seite wird jedoch unabhängig vom Ergebnis ausgewertet.

Beste Übung:Verwenden Sie immer AndAlso, es sei denn, Sie haben einen sehr guten Grund, warum Sie es nicht tun sollten.


In einer Folge wurde gefragt, warum oder wann jemand And anstelle von AndAlso (oder & anstelle von &&) verwenden würde:Hier ist ein Beispiel:

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

In diesem Fall möchte ich sowohl X als auch Y initialisieren.Y muss initialisiert werden, damit y.DoDance ausgeführt werden kann.Allerdings mache ich in der init()-Funktion auch einige zusätzliche Dinge, wie zum Beispiel zu prüfen, ob ein Socket geöffnet ist, und zwar nur, wenn das funktioniert, zum Beispiel beide, sollte ich weitermachen und den x.process(y) ausführen.

Auch dies ist in 99 % der Fälle wahrscheinlich nicht erforderlich und nicht elegant, deshalb habe ich gesagt, dass die Standardeinstellung sein sollte Und auch.

@shsteimer

Das Konzept, auf das sich Bescheidenheit bezieht, ist eine Überlastung des Bedieners.in der Aussage:...A wird zuerst ausgewertet. Wenn es als falsch ausgewertet wird, wird B nie ausgewertet.Gleiches gilt für

Das ist keine Überlastung des Bedieners.Unter „Operatorüberladung“ versteht man die Möglichkeit, benutzerdefiniertes Verhalten für Operatoren wie *, +, = usw. zu definieren.

Auf diese Weise könnten Sie Ihre eigene „Log“-Klasse schreiben und dies dann tun

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.

Dies tun

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

heißt tatsächlich Kurzschlussbewertung

ZombieSheep ist der Volltreffer.Das einzige Problem, das möglicherweise auf Sie wartet, ist, dass dies nur zutrifft, wenn Sie den &&-Operator verwenden.Bei Verwendung des &-Operators werden beide Ausdrücke jedes Mal ausgewertet, unabhängig davon, ob einer oder beide als falsch ausgewertet werden.

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
}

Beachten Sie, dass es einen Unterschied zwischen && und & hinsichtlich der Menge Ihres Ausdrucks gibt, die ausgewertet wird.

&& ist als kurzgeschlossenes boolesches UND bekannt und wird, wie andere hier angemerkt haben, vorzeitig beendet, wenn das Ergebnis ermittelt werden kann, bevor alle Unterausdrücke ausgewertet sind.

& ist als logischer bitweiser Operator bekannt und wertet immer alle Unterausdrücke aus.

Als solche:

if (a() && b())

Werde nur anrufen B Wenn A kehrt zurück WAHR.

allerdings dies:

if (a() & b())

Werde immer beide anrufen A Und B, obwohl das Ergebnis des Aufrufs A ist falsch und somit bekannt FALSCH unabhängig vom Ergebnis des Anrufs B.

Der gleiche Unterschied besteht für das || und | Betreiber.

In einigen Sprachen gibt es interessante Situationen, in denen Ausdrücke in einer anderen Reihenfolge ausgeführt werden.Ich denke speziell an Ruby, aber ich bin sicher, dass sie es von woanders ausgeliehen haben (wahrscheinlich Perl).

Die Ausdrücke in der Logik bleiben von links nach rechts, aber zum Beispiel:

puts message unless message.nil?

Das obige bewertet "message.nil?" Wenn es dann zu False ausgewertet wird (es sei denn, es ist so, wenn es ausgeführt wird, wenn die Bedingung falsch anstelle von True ist), wird "Nachricht" ausgeführt, wodurch der Inhalt der Nachrichtenvariablen zum Bildschirm gedruckt wird.

Manchmal ist es eine interessante Möglichkeit, Ihren Code zu strukturieren ...Ich persönlich verwende es gerne für sehr kurze 1-Liner wie die oben genannten.

Bearbeiten:

Um es etwas klarer zu machen: Das Obige ist dasselbe wie:

unless message.nil?
  puts message
end

Der linke stoppt dann, wenn er null ist.

Bearbeiten:In vb.net werden beide ausgewertet und möglicherweise ein Fehler ausgegeben, es sei denn, Sie verwenden AndAlso

Das Konzept, auf das sich Bescheidenheit bezieht, ist eine Überlastung des Bedieners.in der Aussage:

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

A wird zuerst ausgewertet. Wenn es als falsch ausgewertet wird, wird B nie ausgewertet.Gleiches gilt für

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

A wird zuerst ausgewertet. Wenn es als wahr ausgewertet wird, wird B nie ausgewertet.

Dieses Konzept der Überladung gilt (glaube ich) für alle Sprachen im C-Stil und auch für viele andere.

Nein, zumindest funktioniert der C#-Compiler nicht rückwärts (weder in && noch in ||).Es geht von links nach rechts.

Wenn alle Dinge in einer Reihe stehen, werden sie von links nach rechts ausgeführt.

Wenn Dinge verschachtelt sind, werden sie von innen nach außen ausgeführt.Das mag verwirrend erscheinen, da sich das „Innerste“ normalerweise auf der rechten Seite der Linie befindet, sodass es den Anschein hat, als würde es rückwärts gehen ...

Zum Beispiel

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

Die Dinge passieren so:

  • Anruf GetAddress mit dem wörtlichen "Orion"
  • Anruf GetSummary mit dem wörtlichen "Orion" und das Ergebnis von GetAddress
  • Anruf Foo mit dem wörtlichen 5 und das Ergebnis von GetSummary
  • Weisen Sie diesen Wert zu a

Mir gefallen Orions Antworten.Ich füge zwei Dinge hinzu:

  1. Es gilt immer noch zuerst die Richtung von links nach rechts
  2. Die Innen-zu-Außen-Funktion stellt sicher, dass alle Argumente aufgelöst werden, bevor die Funktion aufgerufen wird

Angenommen, wir haben das folgende Beispiel:

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

Hier ist die Reihenfolge der Ausführung:

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

Ich kann nichts über die rechtlichen Anforderungen von C# sagen (obwohl ich vor dem Schreiben dieses Beitrags ein ähnliches Beispiel mit Mono getestet habe), aber diese Reihenfolge ist in Java garantiert.

Und nur der Vollständigkeit halber (da dies auch ein sprachunabhängiger Thread ist): Es gibt Sprachen wie C und C++, bei denen die Reihenfolge nicht garantiert ist, es sei denn, es gibt einen Sequenzpunkt.Verweise: 1, 2.Bei der Beantwortung der Frage des Threads jedoch: && Und || sind Sequenzpunkte in C++ (sofern nicht überladen;siehe auch OJs ausgezeichnete Antwort).Also einige Beispiele:

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

Im && Fall, foo() läuft garantiert vorher bar() (falls letzteres überhaupt ausgeführt wird), da && ist ein Sequenzpunkt.Im & In diesem Fall wird keine solche Garantie gegeben (in C und C++), und zwar bar() kann vorher laufen foo(), oder umgekehrt.

Was ist ein gutes Beispiel dafür, wann der bitweise Operator anstelle des „kurzgeschlossenen Booleschen“ verwendet werden sollte?

Angenommen, Sie haben Flags, beispielsweise für Dateiattribute.Angenommen, Sie haben READ als 4, WRITE als 2 und EXEC als 1 definiert.Im Binärformat ist das:

READ  0100  
WRITE 0010  
EXEC  0001

Für jedes Flag ist ein Bit gesetzt und jedes ist einzigartig.Mit den bitweisen Operatoren können Sie diese Flags kombinieren:

flags = READ & EXEC; // value of flags is 0101

Ich habe irgendwo gehört, dass Compiler rückwärts arbeiten, bin mir aber nicht sicher, ob das stimmt.

Sie verwenden &, wenn Sie speziell alle Unterausdrücke auswerten möchten, höchstwahrscheinlich, weil sie die gewünschten Nebenwirkungen haben, auch wenn das Endergebnis so sein wird FALSCH und somit nicht ausführen Dann Teil von dir Wenn-Stellungnahme.

Beachten Sie, dass & und | arbeitet sowohl für Bitweisemasken als auch für Boolesche Werte und eignet sich nicht nur für bitweise Operationen.Sie sind angerufen bitweise, aber sie sind in C# sowohl für Ganzzahlen als auch für boolesche Datentypen definiert.

@csmba:

In einer Folge wurde gefragt, warum oder wann jemand And anstelle von AndAlso (oder & anstelle von &&) verwenden würde:Hier ist ein Beispiel:

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

In diesem Fall möchte ich sowohl X als auch Y initialisieren.Y muss initialisiert werden, damit y.DoDance ausgeführt werden kann.Allerdings mache ich in der init()-Funktion auch noch ein paar zusätzliche Dinge, wie z. B. die Prüfung, ob ein Socket geöffnet ist, und nur wenn das klappt, sollte ich für beides mit der Ausführung von x.process(y) fortfahren.

Ich glaube, das ist ziemlich verwirrend.Obwohl Ihr Beispiel funktioniert, ist es nicht der typische Anwendungsfall And (Und ich würde das wahrscheinlich anders schreiben, um es klarer zu machen). And (& in den meisten anderen Sprachen) ist eigentlich die bitweise Und-Operation.Sie würden damit Bitoperationen berechnen, zum Beispiel das Löschen eines Flag-Bits oder das Maskieren und Testen von 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

Die Programmiersprache D tut dies Links-Rechts-Auswertung mit Kurzschluss Und nicht ermöglichen eine Überlastung des && und '||' Betreiber.

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top