Notatka
Dostęp do tej strony wymaga autoryzacji. Może spróbować zalogować się lub zmienić katalogi.
Dostęp do tej strony wymaga autoryzacji. Możesz spróbować zmienić katalogi.
Wskazówka
Ten artykuł jest częścią sekcji Podstawy dla deweloperów, którzy już znają co najmniej jeden język programowania i uczą się języka C#. Jeśli dopiero zaczynasz programować, najpierw zacznij od samouczków Wprowadzenie .
Pochodzi z innego języka? Większość operatorów w tym artykule (+, -, /%||!&&*!=<==>operatory porównania i =) działają tak samo jak w Java, C++i JavaScript. Głównymi niespodziankami dla nowicjuszy są zachowanie dzielenia liczb całkowitych, różnica między formą prefiksową a postfiksową dla ++/-- oraz sposób, w jaki operator przypisania złożonego konwertuje wynik z powrotem do typu wyrażenia po lewej stronie.
Operator łączy jeden lub więcej operandów w jedną wartość. Wiesz już o wyrażeniach i pierwszeństwie operatorów w wyrażeniach języka C#; Ten artykuł zawiera bardziej szczegółowe informacje na temat określonych operatorów, których będziesz używać każdego dnia.
Operatory arytmetyczne
Pięć operatorów arytmetycznych wykonuje obliczenia liczbowe.
| Operator | Name | Przykład | Result |
|---|---|---|---|
+ |
Dodawanie | 10 + 3 |
13 |
- |
Odejmowanie | 10 - 3 |
7 |
* |
Mnożenie | 10 * 3 |
30 |
/ |
Dzielenie | 10 / 3 |
3 |
% |
Upomnienie | 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)
Dzielenie liczb całkowitych obcina się w kierunku zera. Gdy oba operandy są liczbami całkowitymi, / odrzuca część ułamkową: 7 / 2 to 3, a nie 3.5. Obcinanie odbywa się w kierunku zera, a nie w stronę mniejszej wartości: -7 / 2 to -3 (a nie -4). Aby uzyskać wynik dziesiętny, wykonaj co najmniej jeden operand typu zmiennoprzecinkowego: 7.0 / 2 to 3.5. Różni się to od niektórych języków, w których / zawsze tworzy wynik zmiennoprzecinkowy.
Reszta (%) zwraca to, co pozostaje po dzieleniu całkowitym: 10 % 3 to 1, ponieważ 10 = 3 × 3 + 1. Jest to przydatne do iterowania po stałym zakresie (index % length), sprawdzania podzielności (n % 2 == 0) i wyodrębniania cyfr. Z ujemnymi operandami znak wyniku odpowiada znakowi dywidendy (lewy operand): -7 % 3 jest -1 i 7 % -3 ma wartość 1.
Operatory jednoargumentowe
Operatory jednoargumentowe działają na jednym operandie.
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(plus unarny) — pozostawia wartość bez zmian; rzadko zapisywany jawnie, ale poprawny. -
-x(jednoargumentowy minus) — neguje wartość. -
!x(logiczne NOT) — zmieniatruenafalseifalsenatrue. Często będziesz używać!:if (!list.Contains(item)).
Przyrost i dekrementacja
++ dodaje 1 i -- odejmuje 1. Oba mają postać prefiksową i postfiksową, które różnią się tym, jaka wartość jest zwracana:
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
-
Prefiks (
++i,--i): zwiększa lub dekrementuje zmienną jako pierwszą, a następnie zwraca nową wartość. -
Postfix (
i++,i--): zwraca najpierw bieżącą wartość, a następnie zwiększa lub dekrementuje zmienną.
Gdy ++ lub -- pojawia się jako autonomiczna instrukcja (nie część większego wyrażenia), prefiks i postfiks mają taki sam efekt. Rozróżnienie ma znaczenie tylko wtedy, gdy wynik jest używany — na przykład w przypisaniu lub jako argument metody.
Operatory relacyjne
Operatory relacyjne porównują dwie wartości i zwracają bool.
| Operator | Meaning | Przykład |
|---|---|---|
< |
Mniejsze niż | speed < limit |
> |
Większe niż | speed > limit |
<= |
Mniejsze lub równe | score <= 100 |
>= |
Większe niż lub równe | 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)
Operatory relacyjne działają dla wszystkich typów liczbowych i char. Dla char porównanie opiera się na numerycznej wartości punktu kodowego Unicode danego znaku, nie zaś na kolejności alfabetycznej ani specyficznej dla domeny. W powyższym przykładzie ocen 'A' jest większe lub równe 'B', ponieważ 'B' ma wartość Unicode 66, a 'A' ma wartość Unicode 65 — liczby określają porównanie, a nie znaczenie ocen literowych.
Operatory równości
== i != sprawdź, czy dwie wartości są równe, czy nie.
!= jest true wtedy, gdy operandy nie są równe, a false wtedy, gdy są równe.
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
W przypadku typów liczbowych i string, równość testuje wartości. W przypadku typów referencyjnych wartość domyślna to tożsamość (czy dwie zmienne wskazują ten sam obiekt), ale wiele typów, w tym string i record zastępuje tę wartość w celu porównania zawartości. Pełny obraz — sposób działania równości między typami wartości, typami referencyjnymi, rekordami i strukturami — zobacz Porównanie równości.
Note
Język C# nie ma === operatora. Zapis === jest błędem kompilacji:
// This does not compile — C# has no === operator
bool same = (x === 10);
Jeśli pochodzisz z języka JavaScript, użyj polecenia == do porównania wartości (język C# == porównuje już wartość dla typów pierwotnych i ciągów). Typowym powiązanym błędem jest przypadkowe użycie = (operatora przypisania), gdy chodziło o == (sprawdzenie równości). Kompilator wykrywa najczęstsze przypadki, ale dokładnie sprawdź każdy warunek if, który zawiera =.
Operatory logiczne warunkowe
&& (AND) i || (OR) łączą bool wyrażenia.
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)
Oba operatory stosują skrócone wartościowanie: pomijają obliczenie prawego operandu, gdy wynik jest już znany.
-
&&zwracafalse, gdy tylko lewa strona ma wartośćfalse. Prawa strona nigdy nie jest oceniana. -
||zwracatrue, gdy tylko lewa strona ma wartośćtrue. Prawa strona nigdy nie jest oceniana.
Mechanizm skróconego obliczania ma praktyczną zaletę: można bezpiecznie zabezpieczyć wykonanie operacji po prawej stronie przez sprawdzenie po lewej stronie, czy wartość nie jest nullem, jak pokazano w powyższym przykładzie. Jeśli items ma wartość null, na tym && się kończy — items.Count nigdy nie jest wywoływany, więc nie jest zgłaszany żaden NullReferenceException.
Operator warunkowy ?:
Operator warunkowy (nazywany również operatoremternary ) oblicza jedno z dwóch wyrażeń na podstawie warunku:
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
Operator ?: zawsze oblicza dokładnie jedną gałąź — gałąź, która nie spełnia warunku, nigdy nie jest obliczana. Dzięki temu można bezpiecznie użyć wyrażenia po jednej stronie, które zakończy się niepowodzeniem w przypadku innych danych wejściowych, o ile warunek prawidłowo go chroni.
Użyj ?: do prostych wyborów w tekście. W przypadku warunków wielokierunkowych lub bloków kodu if/else instrukcja jest zwykle jaśniejsza.
Operatory przypisania
Prosty operator = przypisania przechowuje wartość w zmiennej:
int level = 1; // declaration + initialization
level = 5; // reassignment
Przypisanie w języku C# jest prawostronnie łączne, co oznacza, że a = b = c = 0 jest obliczane od prawej do lewej: c otrzymuje 0, następnie b otrzymuje a, a potem 0 otrzymuje 0.
Przypisanie złożone
Operatory przypisania złożonego łączą operację binarną z przypisaniem:
| Operator | Odpowiednik |
|---|---|
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
Przypisanie złożone to coś więcej niż tylko skrócony zapis. Oblicza lewą stronę dokładnie raz, a następnie konwertuje wynik z powrotem do typu lewej strony. Ma to znaczenie, gdy lewa strona wyrażenia ma skutki uboczne (na przykład indeksator tablicy), i dlatego przypisanie złożone do zmiennej byte kompiluje się bez jawnego rzutowania, podczas gdy jego rozwinięta postać już nie:
// 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 kompiluje, ponieważ kompilator wstawia konwersję zawężającą automatycznie — wynik 210, mieści się w byte zakresie od 0 do 255.
small = small + 10 wymagałoby jawnego rzutowania na (byte), ponieważ operacje arytmetyczne promują oba operandy do typu int.
Inne operatory języka C#
W tym artykule opisano operatory, które najczęściej spotykasz w kodzie codziennym. Język C# zawiera więcej operatorów przydatnych w określonych scenariuszach:
-
Operatory przesunięcia (
<<,>>,>>>) — przesuwają bity wartości całkowitej w lewo lub w prawo o określoną liczbę pozycji. Bitowe i logiczne operatory liczb całkowitych (&,|,^,~) — łączą lub odwracają wartości całkowite bit po bicie, przydatne do obsługi flag, masek i kodu niskiego poziomu: Operatory bitowe i przesunięć -
checkedandunchecked— określa, czy przepełnienie całkowite zgłasza wyjątek (checked) lub zawija w trybie dyskretnym (unchecked): zaznaczone i niezaznaczone -
Operatory wartości null (
??,??=,?.,?[]) — bezpiecznie obsługują wartościnull, zapewniając wartości domyślne lub skrócony dostęp do składowych: Operatory wartości null -
Operatory sprawdzania typu i konwersji (
is,as,typeof, rzutowanie(T)) — sprawdzanie lub konwertowanie typu wartości w czasie wykonywania: Operatory sprawdzania typu i rzutowania -
Operatory zakresu i indeksu (
..,^) — tworzą zakresy i indeksy względne dla tablic fragmentowania i zakresów: dostęp do składowych i operatory warunkowe o wartości null - Przypisanie dekonstruujące — rozpakowanie krotki lub typu na poszczególne zmienne w jednym wyrażeniu: Dekonstrukcja krotek i innych typów
Zobacz także
- Wyrażenia języka C# — sposób tworzenia wyrażeń i działania pierwszeństwa operatora
-
Porównania równości — jak
==,!=iEqualsdziałają w różnych typach - Operatory i wyrażenia języka C# (odwołanie do języka) — pełna tabela pierwszeństwa i każdy operator