Bearbeiten:
Es wurde ein Beispiel hinzugefügt, das mit der if-else-Anweisung, jedoch nicht mit dem bedingten Operator ausgeführt werden kann.
Schauen Sie sich vor der Antwort bitte um [ Was ist schneller? ] auf Mr. Lipperts Blog. Und ich denke, die Antwort von Herrn Ersönmez ist hier die richtigste.
Ich versuche etwas zu erwähnen, das wir bei einer Programmiersprache auf hohem Niveau berücksichtigen sollten.
Zunächst einmal habe ich noch nie gehört, dass der bedingte Operator schneller sein soll oder die gleiche Leistung wie die if-else-Anweisung in C♯ .
Der Grund ist einfach: Was ist, wenn mit der if-else-Anweisung keine Operation ausgeführt wird:
if (i > 0)
{
value += 2;
}
else
{
}
Die Anforderung des bedingten Operators besteht darin, dass auf beiden Seiten ein Wert vorhanden sein muss , und in C♯ muss auch beide Seiten :
den gleichen Typ haben. Dies unterscheidet es nur von der if-else-Anweisung. So wird Ihre Frage zu einer Frage, wie die Anweisung des Maschinencodes erzeugt wird, so dass sich die Leistung unterscheidet.
Mit dem bedingten Operator ist es semantisch:
Unabhängig davon, welcher Ausdruck ausgewertet wird, gibt es einen Wert.
Aber mit if-else-Anweisung:
Wenn der Ausdruck als wahr ausgewertet wird, tun Sie etwas; Wenn nicht, machen Sie etwas anderes.
Ein Wert ist nicht unbedingt mit der if-else-Anweisung verbunden. Ihre Annahme ist nur mit Optimierung möglich.
Ein weiteres Beispiel, um den Unterschied zwischen ihnen zu demonstrieren, wäre wie folgt:
var array1=new[] { 1, 2, 3 };
var array2=new[] { 5, 6, 7 };
if(i>0)
array1[1]=4;
else
array2[2]=4;
Der obige Code wird jedoch kompiliert. Ersetzen Sie die if-else-Anweisung durch den bedingten Operator.
var array1=new[] { 1, 2, 3 };
var array2=new[] { 5, 6, 7 };
(i>0?array1[1]:array2[2])=4; // incorrect usage
Der bedingte Operator und die if-else-Anweisungen sind konzeptionell gleich, wenn Sie dasselbe tun. Mit dem bedingten Operator in C ist dies möglicherweise sogar noch schneller , da C näher an der Baugruppe der Plattform liegt.
Für den ursprünglichen Code, den Sie angegeben haben, wird der bedingte Operator in einer foreach-Schleife verwendet, die die Dinge durcheinander bringt, um den Unterschied zwischen ihnen zu erkennen. Also schlage ich folgenden Code vor:
public static class TestClass {
public static void TestConditionalOperator(int i) {
long value=0;
value+=i>0?2:3;
}
public static void TestIfElse(int i) {
long value=0;
if(i>0) {
value+=2;
}
else {
value+=3;
}
}
public static void TestMethod() {
TestConditionalOperator(0);
TestIfElse(0);
}
}
und das Folgende sind zwei Versionen der IL von optimiert und nicht. Da sie lang sind, verwende ich ein Bild, um zu zeigen, dass die rechte Seite die optimierte ist:
(Klicken Sie hier, um das Bild in voller Größe anzuzeigen.)
In beiden Codeversionen sieht die IL des bedingten Operators kürzer aus als die if-else-Anweisung, und es besteht immer noch ein Zweifel daran, dass der Maschinencode endgültig generiert wurde. Das Folgende sind die Anweisungen beider Methoden, und das erstere Bild ist nicht optimiert, das letztere ist das optimierte:
Nicht optimierte Anweisungen: (Klicken Sie hier, um das Bild in voller Größe anzuzeigen.)
Optimierte Anweisungen: (Klicken Sie hier, um das Bild in voller Größe anzuzeigen.)
In letzterem ist der gelbe Block der Code, der nur ausgeführt wird, wenn i<=0
, und der blaue Block ist, wenn i>0
. In beiden Versionen von Anweisungen ist die if-else-Anweisung kürzer.
Beachten Sie, dass für verschiedene Anweisungen der [ CPI ] nicht unbedingt gleich ist. Für den identischen Befehl kosten logischerweise mehr Befehle einen längeren Zyklus. Wenn jedoch auch die Abrufzeit des Befehls und die Pipe / der Cache berücksichtigt wurden, hängt die tatsächliche Gesamtausführungszeit vom Prozessor ab. Der Prozessor kann auch die Zweige vorhersagen.
Moderne Prozessoren haben noch mehr Kerne, damit können die Dinge komplexer werden. Wenn Sie ein Intel-Prozessorbenutzer sind, sollten Sie sich [ Referenzhandbuch zur Optimierung von Intel® 64- und IA-32-Architekturen ] ansehen .
Ich weiß nicht, ob es eine Hardware-implementierte CLR gab, aber wenn ja, werden Sie mit dem bedingten Operator wahrscheinlich schneller, weil die IL offensichtlich geringer ist.
Hinweis: Der gesamte Maschinencode ist x86.
DateTime
zur Messung der Leistung verwenden. Verwenden SieStopwatch
. Als nächstes etwas länger - das ist eine sehr kurze Zeit zum Messen.