C#-Operatoren

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? Die meisten Operatoren in diesem Artikel (+, *, /, %, &&, ||, <, ==, >, !, !=, =, Vergleichsoperatoren und -) funktionieren genauso wie in Java, C++ und JavaScript. Die wichtigsten Überraschungen für Neulinge sind das Verhalten der ganzzahligen Division, der Unterschied zwischen Präfix- und Postfixnotation bei ++/-- und die Art und Weise, wie die kombinierte Zuweisung wieder in den Typ der linken Seite umwandelt.

Ein Operator kombiniert einen oder mehrere Operanden in einem einzelnen Wert. Sie wissen bereits über Ausdrücke und Operatorrangfolgen aus C#-Ausdrücken; Dieser Artikel befasst sich mit den spezifischen Operatoren, die Sie täglich verwenden werden.

Arithmetische operatoren

Die fünf arithmetischen Operatoren führen numerische Berechnungen durch.

Operator Name Example Result
+ Zusatz 10 + 3 13
- Subtraktion 10 - 3 7
* Multiplikation 10 * 3 30
/ Abteilung 10 / 3 3
% Rest 10 % 3 1
int apples = 10;
int oranges = 3;

Console.WriteLine(apples + oranges);  // => 13  (addition)
Console.WriteLine(apples - oranges);  // => 7   (subtraction)
Console.WriteLine(apples * oranges);  // => 30  (multiplication)
Console.WriteLine(apples / oranges);  // => 3   (integer division: truncates toward zero)
Console.WriteLine(apples % oranges);  // => 1   (remainder)

// Integer division always truncates toward zero — the fractional part is discarded
int result = 7 / 2;
Console.WriteLine(result); // => 3, not 3.5

// Truncation applies to negative results too: -7 / 2 is -3, not -4
int negResult = -7 / 2;
Console.WriteLine(negResult); // => -3

// To get a decimal result, at least one operand must be a double or float
double precise = 7.0 / 2;
Console.WriteLine(precise); // => 3.5

// Remainder with negative operands: the sign of the result matches the dividend
Console.WriteLine(-7 % 3);  // => -1  (-7 = 3 × -2 + (-1))
Console.WriteLine(7 % -3);  // => 1   ( 7 = -3 × -2 + 1)

Ganzzahlige Division schneidet in Richtung Null ab. Wenn beide Operanden ganze Zahlen sind, verwirft / den Nachkommateil: 7 / 2 ist 3, nicht 3.5. Die Abkürzung liegt in Richtung Null, nicht in Richtung der kleineren Zahl: -7 / 2 ist -3 (nicht -4). Um ein Dezimalergebnis zu erhalten, erstellen Sie mindestens einen Operanden als Gleitkommatyp: 7.0 / 2 ist 3.5. Dies unterscheidet sich von einigen Sprachen, in denen / immer ein Gleitkommaergebnis erzeugt wird.

Rest (%) liefert den Rest nach ganzzahliger Division: 1 ist 10 = 3 × 3 + 1, weil 10 % 3. Es ist nützlich, einen festen Bereich (index % length) zu durchlaufen, die Teilbarkeit (n % 2 == 0) zu prüfen und Ziffern zu extrahieren. Bei negativen Operanden entspricht das Zeichen des Ergebnisses dem Zeichen der Dividende (der linke Operand): -7 % 3 ist -1 und 7 % -3 ist 1.

Unäre Operatoren

Unäre Operatoren arbeiten mit einem einzelnen Operanden.

int temperature = 20;
int windChill = -5;

int heatIndex = +temperature;   // unary +: value unchanged (rarely needed)
int coldFactor = -windChill;    // unary -: negates the value → 5

Console.WriteLine(heatIndex);   // => 20
Console.WriteLine(coldFactor);  // => 5

bool isRaining = false;
bool isSunny = !isRaining;     // logical NOT: flips true/false
Console.WriteLine(isSunny);    // => True
  • +x (unär plus) — lässt den Wert unverändert; nur selten explizit geschrieben, aber gültig.
  • -x (unär minus) - negiert den Wert.
  • !x (logisches NOT) — kehrt true in false um und false in true. Sie werden häufig verwenden ! : if (!list.Contains(item)).

Schrittweises Erhöhen und Verringern

++ addiert 1 und -- subtrahiert 1. Beide weisen ein Präfixformular und ein Postfixformular auf, das sich in dem zurückgegebenen Wert unterscheidet:

int counter = 5;

// Prefix: increment first, then use the new value
int a = ++counter;
Console.WriteLine(a);       // => 6
Console.WriteLine(counter); // => 6

// Postfix: use the current value first, then increment
int b = counter++;
Console.WriteLine(b);       // => 6  (value before increment)
Console.WriteLine(counter); // => 7  (incremented after)

// Decrement works the same way
int score = 10;
Console.WriteLine(score--); // => 10 (current value; score becomes 9)
Console.WriteLine(score);   // => 9
  • Präfix (++i, --i): erhöht oder dekrementiert zuerst die Variable, und gibt dann den neuen Wert zurück.
  • Postfix (i++, i--): gibt zuerst den aktuellen Wert zurück und inkrementiert oder dekrementiert dann die Variable.

Wenn ++ oder -- als eigenständige Anweisung steht (nicht als Teil eines größeren Ausdrucks), haben Präfix und Postfix die gleiche Wirkung. Die Unterscheidung ist nur dann wichtig, wenn das Ergebnis verwendet wird , z. B. in einer Zuordnung oder als Methodenargument.

Relationale Operatoren

Relationale Operatoren vergleichen zwei Werte und geben ein bool.

Operator Dies bedeutet Example
< Kleiner als speed < limit
> Größer als speed > limit
<= Kleiner oder gleich score <= 100
>= Größer als oder gleich score >= 0
int speed = 75;
int limit = 60;

Console.WriteLine(speed > limit);   // => True   (greater than)
Console.WriteLine(speed < limit);   // => False  (less than)
Console.WriteLine(speed >= limit);  // => True   (greater than or equal)
Console.WriteLine(speed <= limit);  // => False  (less than or equal)

// Relational operators work on all numeric types and char
// char comparison uses the character's numeric Unicode code point, not alphabetical position
// 'B' (U+0042, value 66) is less than 'A' (U+0041, value 65)? No — 'A' (65) < 'B' (66)
char grade = 'B';
Console.WriteLine(grade >= 'A' && grade <= 'C'); // => True  ('A'=65 <= 'B'=66 <= 'C'=67)

Relationale Operatoren arbeiten an allen numerischen Typen und char. Für char wird der numerische Unicode-Codepoint-Wert des Zeichens und nicht eine alphabetische oder domänenspezifische Reihenfolge verwendet. Im obigen Benotungsbeispiel ist 'A' größer oder gleich 'B', weil 'B' den Unicode-Wert 66 und 'A' den Unicode-Wert 65 hat – die Zahlen bestimmen den Vergleich, nicht die Bedeutung der Buchstabennoten.

Gleichheitsoperatoren

== und != überprüfen Sie, ob zwei Werte gleich sind oder nicht. != ist true, wenn die Operanden nicht gleich sind, und false, wenn sie es sind.

int expected = 42;
int actual = 42;

Console.WriteLine(actual == expected);  // => True   (values are equal)
Console.WriteLine(actual != expected);  // => False  (true when values are not equal)

string name = "Alice";
Console.WriteLine(name == "Alice");  // => True   (string content matches)
Console.WriteLine(name == "alice");  // => False  (case-sensitive)

int x = 5;
Console.WriteLine(x == 10);  // => False

Bei numerischen Typen und string vergleicht die Gleichheit die Werte. Bei Verweistypen ist der Standard die Identität (also ob zwei Variablen auf dasselbe Objekt verweisen), aber viele Typen, darunter string und record, überschreiben dieses Verhalten, um den Inhalt zu vergleichen. Das vollständige Bild – funktionsweise der Gleichheit zwischen Werttypen, Referenztypen, Datensätzen und Strukturen – finden Sie unter Gleichheitsvergleiche.

Note

C# verfügt nicht über einen === Operator. Beim Schreiben === handelt es sich um einen Kompilierungszeitfehler:

// This does not compile — C# has no === operator
bool same = (x === 10);

Wenn Sie von JavaScript kommen, verwenden Sie == zum Vergleichen von Werten (C# == vergleicht bei primitiven Typen und Zeichenfolgen bereits nach dem Wert). Ein häufiger verwandter Fehler ist, versehentlich = (Zuweisung) zu schreiben, obwohl eigentlich == (Gleichheitsprüfung) gemeint ist. Der Compiler erkennt die häufigsten Formen, aber überprüfen Sie jede if-Bedingung, die = enthält, noch einmal.

Bedingte logische Operatoren

&& (AND) und || (OR) kombinieren bool Ausdrücke.

int age = 20;
bool hasTicket = true;

// && (AND): both sides must be true
bool canEnter = age >= 18 && hasTicket;
Console.WriteLine(canEnter); // => True

// || (OR): at least one side must be true
bool freeEntry = age < 5 || age >= 65;
Console.WriteLine(freeEntry); // => False

// Short-circuit: right side is skipped when the result is already determined
// Here, items.Count is never called if items is null
List<string>? items = null;
bool hasItems = items != null && items.Count > 0;
Console.WriteLine(hasItems); // => False  (short-circuits; no NullReferenceException)

Beide Operatoren verwenden Kurzschlussauswertung: Sie überspringen die Auswertung des rechten Operanden, wenn das Ergebnis bereits feststeht.

  • && gibt false zurück, sobald die linke Seite false ist. Die rechte Seite wird nie ausgewertet.
  • || gibt true zurück, sobald die linke Seite true ist. Die rechte Seite wird nie ausgewertet.

Das Kurzschlussverhalten bietet einen praktischen Vorteil: Sie können damit einen Vorgang auf der rechten Seite durch eine Nullprüfung auf der linken Seite sicher absichern, wie das obige Beispiel zeigt. Wenn itemsnull ist, stoppt && dort — items.Count wird nie aufgerufen, sodass kein NullReferenceException geworfen wird.

Bedingter Operator ?:

Der bedingte Operator (auch als ternärer Operator bezeichnet) wertet einen von zwei Ausdrücken basierend auf einer Bedingung aus:

condition ? value-when-true : value-when-false
int temperature2 = 35;

// condition ? value-when-true : value-when-false
string weather = temperature2 > 30 ? "hot" : "comfortable";
Console.WriteLine(weather); // => hot

// Only the matching branch evaluates — the other branch is never run
int divisor = 0;
// The division 10 / divisor is never evaluated because divisor == 0 is true
int safe = divisor == 0 ? -1 : 10 / divisor;
Console.WriteLine(safe); // => -1

Der ?: Operator wertet immer genau eine Verzweigung aus – die Seite, die nicht mit der Bedingung übereinstimmt, wird nie ausgewertet. Dadurch ist es sicher, einen Ausdruck auf einer Seite zu verwenden, der für andere Eingaben fehlschlägt, solange die Bedingung sie ordnungsgemäß schützt.

Verwenden Sie ?: für einfache Inline-Auswahlmöglichkeiten. Bei mehrwegigen Bedingungen oder Codeblöcken ist eine if/else Anweisung in der Regel klarer.

Zuweisungsoperatoren

Der Operator für einfache Zuordnung = speichert einen Wert in einer Variablen:

int level = 1;  // declaration + initialization
level = 5;      // reassignment

Die Zuweisung in C# ist rechtsassoziativ, das heißt, dass a = b = c = 0 von rechts nach links ausgewertet wird: c erhält 0, dann erhält b0, dann erhält a0.

Verbundzuweisung

Zusammengesetzte Zuordnungsoperatoren kombinieren einen binären Vorgang mit Zuordnung:

Operator Entspricht
x += y x = x + y
x -= y x = x - y
x *= y x = x * y
x /= y x = x / y
x %= y x = x % y
int level = 1;
level = 5;          // simple assignment: replaces the value
Console.WriteLine(level); // => 5

// Compound assignment: short form of binary operation + assignment
int hp = 100;
hp += 20;   // same as: hp = hp + 20
Console.WriteLine(hp); // => 120
hp -= 10;   // same as: hp = hp - 10
Console.WriteLine(hp); // => 110
hp *= 2;    // same as: hp = hp * 2
Console.WriteLine(hp); // => 220
hp /= 3;    // same as: hp = hp / 3 (integer division)
Console.WriteLine(hp); // => 73
hp %= 7;    // same as: hp = hp % 7
Console.WriteLine(hp); // => 3

Zusammengesetzte Zuordnung ist mehr als nur eine Kurzform. Sie wertet die linke Seite genau einmal aus und konvertiert das Ergebnis dann wieder in den linken Seitentyp. Das ist wichtig, wenn die linke Seite Nebeneffekte hat (z. B. ein Array-Indexer), und erklärt, warum eine Verbundzuweisung für eine Variable vom Typ byte ohne expliziten Cast kompiliert, während die ausgeschriebene Form dies nicht tut:

// Assignment is right-associative: evaluated right to left
int a2, b2, c2;
a2 = b2 = c2 = 0;     // c2 = 0 first, then b2 = 0, then a2 = 0
Console.WriteLine($"{a2} {b2} {c2}"); // => 0 0 0

// Compound assignment evaluates the left side once and converts back to the LHS type
byte small = 200;
small += 10;  // equivalent to: small = (byte)(small + 10); result is 210
Console.WriteLine(small); // => 210

small += 10 kompiliert, da der Compiler die Schmalungskonvertierung automatisch einfügt – das Ergebnis , 210passt in den byte Bereich von 0 bis 255. small = small + 10 würde eine explizite (byte) Typumwandlung erfordern, weil die arithmetische Operation beide Operanden in int umwandelt.

Andere C#-Operatoren

In diesem Artikel werden die Operatoren behandelt, die sie am häufigsten im alltäglichen Code finden. Die C#-Sprache enthält weitere Operatoren, die in bestimmten Szenarien nützlich sind:

  • Umschaltoperatoren (<<, >>, >>>) – Verschieben der Bits eines ganzzahligen Werts um eine bestimmte Anzahl von Positionen nach links oder rechts. Bitweise und ganzzahlige logische Operatoren (&, |, , ^~) – Kombinieren oder Umkehren ganzzahliger Werte jeweils ein Bit, nützlich bei Flags, Masken und Code auf niedriger Ebene: Bitweise und Umschaltoperatoren
  • checked und unchecked — steuern, ob ein Ganzzahlüberlauf eine Ausnahme auslöst (checked) oder stillschweigend einen Umbruch ausführt (unchecked): checked und unchecked
  • Null-Operatoren (??, ??=, ?., ?[]) — null-Werte sicher behandeln, indem Standardwerte bereitgestellt oder der Memberzugriff kurzgeschlossen wird: Null-Operatoren
  • Typprüfungs- und Konvertierungsoperatoren (is, as, typeof, cast (T)) — den Laufzeittyp eines Werts prüfen oder einen Wert konvertieren: Operatoren für Typprüfung und Typumwandlung
  • Bereichs- und Indexoperatoren (.., ^) — erzeugen Bereiche und end-relative Indizes zum Aufteilen von Arrays und Spans: Memberzugriffs- und nullbedingte Operatoren
  • Dekonstruktionszuweisung — Entpacken eines Tupels oder Typs in einzelne Variablen in einem einzigen Ausdruck: Dekonstruktion von Tupeln und anderen Typen

Siehe auch