Hinweis
Für den Zugriff auf diese Seite ist eine Autorisierung erforderlich. Sie können versuchen, sich anzumelden oder das Verzeichnis zu wechseln.
Für den Zugriff auf diese Seite ist eine Autorisierung erforderlich. Sie können versuchen, das Verzeichnis zu wechseln.
Tip
Dieser Artikel ist Teil des Abschnitts "Grundlagen" für Entwickler, die bereits mindestens eine Programmiersprache kennen und C# erlernen. Wenn Sie noch nicht mit der Programmierung vertraut sind, beginnen Sie zuerst mit den Lernprogrammen " Erste Schritte ".
Kommen Sie aus einer anderen Sprache? Ausdrücke in C# funktionieren ähnlich wie in Java, C++ und JavaScript. Ein Unterschied ist zu beachten: Zusammengesetzte Zuordnungsoperatoren wie += und der Inkrementoperator ++ sind Ausdrücke in C#, sodass sie in größeren Ausdrücken angezeigt werden können.
Ein Ausdruck ist ein Codeteil, den der Compiler auswertet, um einen Wert zu erzeugen – eine Zahl, eine Zeichenfolge, einen Verweis oder ein bool. Zum Beispiel ist 11 ein Ausdruck, der zu der Ganzzahl total > 10 ausgewertet wird, und 3 + 4 * 2 ist ein Ausdruck, der zu true oder false ausgewertet wird.
Die einfachsten Ausdrücke sind Literale (wie 42 oder "hello") und Variablennamen (z. B total. ). Sie erstellen komplexere Ausdrücke, indem Sie einfachere Ausdrücke mit Operatoren kombinieren.
Ausdrücke und Anweisungen
Ein Ausdruck erzeugt einen Wert. Eine Anweisung ist ein vollständiger Befehl, den das Programm ausführt. Viele Aussagen enthalten Ausdrücke. Beispielsweise ist int total = 3 + 4 * 2; eine Anweisung zur Variablendeklaration. Der Compiler wertet den Initialisierungsausdruck 3 + 4 * 2 aus, der 11 erzeugt, und weist diesen Wert der neuen Variablen total zu.
Einen Ausdruck können Sie sich wie eine Wortgruppe und eine C#-Anweisung wie einen vollständigen Satz vorstellen. Diese Arbeitsdefinitionen helfen Ihnen, die formale Terminologie und die Erklärungen zu verstehen, auf die Sie stoßen werden, wenn Sie mehr über C# lernen, obwohl Sie sich diesen Unterschied im normalen Programmieralltag nur selten bewusst machen müssen.
Kombinieren von Ausdrücken
Ausdrücke können kombiniert werden. Gehen Sie von 3 + 4 * 2 aus. Dieser einzelne Ausdruck enthält tatsächlich zwei kleinere Ausdrücke: den Multiplikationsausdruck4 * 2 und den Additionsausdruck3 + <result>. Wenn Ausdrücke kombiniert werden, benötigt C# eine Regel, um zu entscheiden, welche zuerst ausgewertet werden soll. Diese Regel ist die Rangfolge des Operators.
Sie müssen sich die vollständige Präzedenzhierarchie nicht merken. Der nächste Abschnitt fasst die üblichen Gruppen zusammen, und mit Klammern können Sie die Reihenfolge immer ausdrücklich angeben, wenn Sie sich nicht sicher sind.
Rangfolge der Operatoren
Die Rangfolge des Operators bestimmt, wie ein kombinierter Ausdruck in Unterausdrücke gruppiert wird. Dieses Konzept ähnelt den Regeln der Reihenfolge von Vorgängen aus der mathematischen Klasse. Ein Operator mit höherer Rangfolge bindet enger an seine Operanden. Der Ausdruck ist so strukturiert, als wären diese Operanden zusammen in Klammern gesetzt. In 3 + 4 * 2 hat * eine höhere Priorität als +, daher wird der Ausdruck als 3 + (4 * 2) gruppiert, nicht als (3 + 4) * 2.
C# hat mehr Rangfolgegruppen als die hier zusammengefassten vier. Diese zusätzlichen Gruppen setzen bekannte Regeln durch — zum Beispiel Multiplikation vor der Addition — und decken die gesamte Menge an Operatoren ab. In den folgenden Gruppen wird beschrieben, was sie am häufigsten im alltäglichen Code finden:
-
Primär, unär und Bereich – dies sind drei unterschiedliche Rangfolgegruppen, die alle enger binden als arithmetisch. Diese Zusammenfassung kombiniert sie in einem Schritt, da sie für praktische Zwecke alle vor arithmetischen Zwecken angewendet werden.
-
Primäre Operatoren – Memberzugriff (
x.y), Methodenaufrufe (f()), Indexzugriff (a[i]) und NULL-bedingter Zugriff (?.,?[]) – haben von allen die höchste Bindungsstärke. -
Unäre Operatoren wirken auf einen einzelnen Operanden: Negation (
-x), logische NOT (!flag), Präfixinkrement (++i) und Postfix-Inkrement (i++). - Der range-Operator (
..) bildet Indexbereiche für Slice-Ausdrücke wiearray[1..4].
-
Primäre Operatoren – Memberzugriff (
-
Arithmetische Operatoren —
*,%,/binden stärker als+und-. Multiplikation und Division erfolgen vor Addition und Subtraktion. -
Vergleich —
<,>,<=,==,>=,!=binden schwächer als arithmetische Operatoren, sodass arithmetische Operationen vor dem Vergleich ausgeführt werden. -
Logisch —
&&und||binden von den gebräuchlichen Operatoren am schwächsten, sodass Vergleiche vor der logischen Verknüpfung ausgewertet werden.
Diese Priorität bedeutet, dass der Ausdruck score + bonus > threshold && attempts < maxAttempts genau so ausgewertet wird, wie Sie ihn lesen würden: Addieren Sie score und bonus, vergleichen Sie die Summe mit threshold, vergleichen Sie attempts mit maxAttempts, und kombinieren Sie dann die beiden bool-Ergebnisse mit &&. Das Hinzufügen von Klammern, um jede Gruppierung explizit zu machen, zeigt die gleiche Struktur an: ((score + bonus) > threshold) && (attempts < maxAttempts).
Die vollständige Rangfolgehierarchie, die alle Operatoren abdeckt, finden Sie unter C#-Operatoren und Ausdrücken.
Verwenden Sie Klammern, um die Absicht klarzumachen
Klammern setzen Vorrang außer Kraft und dokumentieren Ihre Absicht gleichzeitig. Wenn die Reihenfolge aus den oben genannten Gruppen nicht offensichtlich ist, fügen Sie Klammern hinzu:
int score = 80;
int bonus = 15;
int threshold = 90;
bool eligible = true;
// Without parentheses: || binds less tightly than &&, so this reads as:
// eligible && (score + bonus > threshold) || bonus > 20
bool result1 = eligible && score + bonus > threshold || bonus > 20;
// With parentheses: forces the || to combine two complete conditions
bool result2 = (eligible && score + bonus > threshold) || bonus > 20;
Console.WriteLine(result1); // => True
Console.WriteLine(result2); // => True
// Parentheses can also change the result:
bool isAdmin = false;
bool isOwner = true;
// Without: && binds tighter, so: (isAdmin && isOwner) || true
bool access1 = isAdmin && isOwner || true;
// With: forces the || to run first
bool access2 = isAdmin && (isOwner || true);
Console.WriteLine(access1); // => True (false && true is false; false || true is true)
Console.WriteLine(access2); // => False (false && anything is false)
Die letzten beiden Zeilen zeigen, dass Klammern das Ergebnis ändern können, nicht nur den Stil. Wenn && und || zusammen angezeigt werden, fügen Sie Klammern hinzu, um herauszugeben, welche Bedingung zuerst kombiniert wird. Ein Leser, der (isAdmin && isOwner) || isSuperUser sieht, kennt die Absicht sofort.
Auswertung von Ausdrücken
Das Verständnis, wie C# kombinierte Ausdrücke auswertet, ist mit einer Analogie einfacher. Stellen Sie sich vor, ein komplexes mathematisches Problem mit Bleistift und Papier zu bearbeiten: Sie identifizieren den innersten oder höchsten Unterausdruck, berechnen ihren Zwischenwert, notieren das Ergebnis, und wiederholen Sie dann den nächsten Unterausdruck, bis Sie die endgültige Antwort erreicht haben.
C# folgt demselben Prozess, der von zwei Regeln geleitet wird:
Regel 1: Operanden werden von links nach rechts ausgewertet. Bei jedem binären Ausdruck müssen beide Operanden vollständig ausgewertet werden, bevor der Operator angewendet wird. C# wertet zuerst den linken Operanden aus, dann den rechten und führt anschließend die Operation aus.
Regel 2: Einige Operatoren werten verkürzt aus. Bestimmte Operatoren beenden die Auswertung, sobald das Ergebnis ermittelt wird, und überspringt alle verbleibenden Operanden:
-
&&(bedingte UND): gibtfalsezurück, sobald die linke Seitefalseist. Die rechte Seite wird nie ausgewertet. -
||(bedingtes ODER): gibttruezurück, sobald die linke Seitetrueist. Die rechte Seite wird nie ausgewertet. -
?:(bedingt/ternär): Wertet nur die Verzweigung aus, die der Bedingung entspricht – die andere Verzweigung wird nie ausgewertet. -
?.(nullbedingter Memberzugriff) und?[](nullbedingter Elementzugriff): Brechen Sie ab und geben Sie sofortnullzurück, wenn die linke Seitenullist, und überspringen Sie dabei den Memberzugriff bzw. den Index. -
??=(Null-Koalescing-Zuordnung): Weist die rechte Seite nur zu, wenn die linke Seite istnull.
Papier- und Bleistiftauswertung
Betrachten Sie den Ausdruck 3 + 6 / 2. Obwohl die Addition in der Lesereihenfolge zuerst erscheint, hat / Vorrang vor +, sodass 6 / 2 der Unterausdruck ist, der zuerst ausgewertet wird. Schrittweises Durcharbeiten – genau wie auf Papier:
3 + 6 / 2
↓ (evaluate 6 / 2 → 3)
3 + 3
↓ (evaluate 3 + 3 → 6)
6
// 3 + 6 / 2
// Step 1: 6 / 2 has higher precedence → interim value 3
// Step 2: 3 + 3 → final result 6
int result = 3 + 6 / 2;
Console.WriteLine(result); // => 6
Der von 6 / 2 erzeugte Zwischenwert 3 wird zum rechten Operanden von +, und das endgültige Ergebnis ist 6. Jeder Unterausdruck erzeugt einen Zwischenwert; Diese Zwischenwerte feeden den nächsten Unterausdruck, bis nur ein Wert verbleibt.
Associativity ist ein verwandtes Konzept: Wenn zwei Operatoren die gleiche Priorität haben, entscheidet Associativität, welches zuerst geht. Die meisten C#-Operatoren sind linksassoziativ, d. h. sie gruppieren von links nach rechts. Das a - b - c ist also identisch mit (a - b) - c, nicht a - (b - c).
Kurzschlussauswertung in der Praxis
Die Kurzschlussauswertung ist besonders nützlich für Nullprüfungen:
string? text = null;
// Safe: second condition runs only when text is not null
bool hasContent = text != null && text.Length > 0;
Console.WriteLine(hasContent); // => False (short-circuits after null check; no NullReferenceException)
text = "hello";
hasContent = text != null && text.Length > 0;
Console.WriteLine(hasContent); // => True
// || short-circuits on true: right side is never evaluated when left side is true
string word = "hello";
bool anyMatch = word.StartsWith("h") || word.StartsWith("x");
Console.WriteLine(anyMatch); // => True (right side never evaluated)
// ?. short-circuits on null: returns null without accessing .Length
string? maybeNull = null;
int? length = maybeNull?.Length; // length is null; no NullReferenceException
Console.WriteLine(length.HasValue); // => False
text != null && text.Length > 0 ist sicher, weil die zweite Bedingung nur dann ausgewertet wird, wenn text nicht null ist. In ähnlicher Weise bricht ?. die Auswertung ab, wenn es auf eine null-Referenz trifft, wodurch eine NullReferenceException ohne explizite if-Prüfung vermieden wird.
Einen umfassenderen Blick auf nullsichere Operatoren finden Sie unter C#-Null-Operatoren.
Siehe auch
- C#-Operatoren und Ausdrücke (Sprachreferenz) – vollständige Rangfolgetabelle und jeder Operator
- Arithmetische, Vergleichs-, Logische und Zuordnungsoperatoren – die täglichen Operatoren im Detail
-
Gleichheitsvergleiche – wie
==,!=undEqualsfunktionieren -
C#-Nulloperatoren –
?.,??und??= - Logische boolesche Operatoren