Operator menerima satu, dua atau tiga operand lalu menghasilkan sebuah nilai: a + b, !done, x ?? fallback. Operator di C# mirip dengan operator di C, Java dan JavaScript, tapi beberapa di antaranya berperilaku dengan cara yang mengejutkan pemula, terutama pembagian bilangan bulat dan tanda hasil %.
Operator aritmetika
+, -, *, / dan % bekerja pada setiap tipe numerik. Tipe hasilnya mengikuti operand-nya: dua nilai int menghasilkan int, sedangkan int dan double menghasilkan double.
Output:
22
12
85
3
2
3.4
3.4
3
3.4
Pembagian bilangan bulat dibulatkan ke arah nol. 17 / 5 hasilnya 3 dan -17 / 5 hasilnya -3. Ini menyebabkan bug yang sangat umum: int percent = done / total * 100; bernilai 0 setiap kali done < total, karena done / total sudah bernilai 0. Kalikan dulu (done * 100 / total) atau bagi sebagai double.
Membagi bilangan bulat atau decimal dengan nol melempar DivideByZeroException. Membagi double dengan nol tidak melempar exception; hasilnya tak hingga, atau NaN untuk 0.0 / 0.0:
Output:
True
True
False
DivideByZeroException
Operator modulo dan bilangan negatif
% mengembalikan sisa pembagian, dan hasilnya mengikuti tanda operand kiri. Ini berbeda dari Python dan dari "mod" dalam matematika, yang selalu tidak negatif untuk pembagi positif:
Output:
1
-1
1
2
even
62 min 5 s
Thu
1.5
Pakai fungsi bantu Mod setiap kali sisi kirinya bisa negatif dan hasilnya dipakai sebagai indeks: days[(today + offset) % 7] akan melempar IndexOutOfRangeException kalau jumlahnya negatif. Memeriksa bilangan ganjil punya jebakan yang sama: n % 2 == 1 bernilai false untuk bilangan ganjil negatif; periksa dengan n % 2 != 0.
Assignment, compound assignment dan increment
= memberikan nilai. Bentuk compound +=, -=, *=, /=, %=, &=, |=, ^=, <<=, >>= menggabungkan sebuah operasi dengan pemberian nilai. ++ dan -- menambah atau mengurangi 1, dan tersedia dalam bentuk prefix dan postfix yang berbeda pada nilai yang dikembalikannya:
Output:
14
start, step
a=5 b=7 i=7
4
Kasus byte memperlihatkan sebuah keanehan: level = level + 10; tidak bisa di-compile, karena byte + int menghasilkan int, tapi level += 10; bisa, karena compound assignment menyertakan cast implisit kembali ke tipe variabelnya. Cast itu berputar balik saat terjadi overflow (250 + 10 menjadi 4).
Operator perbandingan dan logika
Operator perbandingan (==, !=, <, >, <=, >=) mengembalikan bool. Untuk string, == membandingkan teksnya, bukan referensinya. Operator logikanya adalah ! (tidak), && (dan), || (atau) dan ^ (eksklusif atau).
Output:
True
no active user
with ||:
evaluated A
with |:
evaluated A
evaluated B
True
&& dan || melakukan short-circuit: operand kanan hanya dijalankan saat bisa mengubah hasilnya. Itulah yang membuat user != null && user.IsActive aman. & dan | tunggal pada boolean selalu mengevaluasi kedua sisinya, yang jarang sekali kamu inginkan dalam sebuah kondisi.
Operator bitwise dan shift
Pada tipe bilangan bulat, &, |, ^ dan ~ bekerja pada bit satu per satu, sedangkan << dan >> menggesernya. Operator-operator ini dipakai untuk flag, mask, hashing dan protokol tingkat rendah:
Output:
3
True
False
101
1024
125
5
-1
Untuk kumpulan flag yang bernama, enum dengan atribut [Flags] lebih jelas daripada konstanta bilangan bulat, dan HasFlag lebih enak dibaca daripada sebuah mask. C# 11 menambahkan >>>, yaitu right shift tanpa tanda yang mengisi dengan nol bahkan untuk bilangan negatif.
Operator null
Ada tiga operator untuk bekerja dengan nilai yang mungkin null:
Output:
Guest
0
5
a ?? b mengembalikan a kecuali nilainya null, dan kalau null mengembalikan b. a?.Member mengembalikan null alih-alih melempar exception saat a bernilai null. C# 8 menambahkan a ??= b, yang memberikan b ke a hanya saat a bernilai null. Semuanya dibahas secara mendalam di nullable type.
Prioritas operator
Saat sebuah ekspresi mencampur beberapa operator, baris yang lebih tinggi mengikat lebih kuat. Operator di baris yang sama dikelompokkan dari kiri ke kanan, kecuali assignment, ?? dan ?:, yang dikelompokkan dari kanan ke kiri. (Operand-nya sendiri selalu dievaluasi dari kiri ke kanan.)
| Kategori | Operator |
|---|---|
| Primary | x.y, x?.y, f(x), a[i], x++, x--, new, typeof, nameof |
| Unary | +x, -x, !x, ~x, ++x, --x, (T)x, await |
| Perkalian | *, /, % |
| Penjumlahan | +, - |
| Shift | <<, >>, >>> |
| Relasional dan pengujian tipe | <, >, <=, >=, is, as |
| Kesamaan | ==, != |
| AND bitwise | & |
| XOR bitwise | ^ |
| OR bitwise | | |
| AND kondisional | && |
| OR kondisional | || |
| Null coalescing | ?? |
| Kondisional | c ? a : b |
| Assignment dan lambda | =, +=, -=, ??=, =>, dan bentuk compound lainnya |
Ada dua akibat yang perlu kamu tahu: a + b * c melakukan perkalian terlebih dahulu, dan x & mask == 0 melakukan perbandingan terlebih dahulu (== mengikat lebih kuat daripada &), jadi artinya x & (mask == 0) dan tidak bisa di-compile untuk bilangan bulat. Tulis (x & mask) == 0. Tanda kurung tidak ada ruginya dan membuat maksudmu jelas.
Operator overloading
Tipe buatanmu sendiri bisa mendefinisikan arti sebuah operator. Dengan cara inilah decimal, DateTime dan TimeSpan mendukung + dan <:
Output:
33.49
True
Operator harus public static, dan beberapa operator harus dibuat berpasangan: mendefinisikan < mewajibkan >, dan == mewajibkan !=. Setelah == didefinisikan, compiler juga memberi warning sampai kamu meng-override Equals dan GetHashCode agar sesuai. Lakukan overload operator hanya di tempat artinya sudah jelas, seperti pada angka, vektor dan uang.
Pertanyaan yang sering diajukan
Apa yang dilakukan % di C#?
% adalah operator sisa bagi: 17 % 5 hasilnya 2. Tanda hasilnya mengikuti operand kiri, jadi -7 % 3 hasilnya -1, bukan 2 seperti di Python. Untuk hasil yang selalu tidak negatif, seperti yang kamu butuhkan saat memutar sebuah indeks, tulis ((a % n) + n) % n. Operator ini juga bekerja pada double dan decimal: 7.5 % 2 hasilnya 1,5.
Kenapa 7 / 2 hasilnya 3 di C#?
Saat kedua operand adalah bilangan bulat, / melakukan pembagian bilangan bulat dan membuang bagian pecahannya, dibulatkan ke arah nol. Jadikan salah satu operand bilangan floating-point atau decimal untuk mendapatkan hasil pecahan: 7 / 2.0 hasilnya 3,5, (double)a / b mengonversi sebelum membagi, dan 7m / 2 hasilnya 3,5 sebagai decimal.
Apa perbedaan && dan & di C#?
&& adalah AND kondisional: kalau sisi kirinya false, sisi kanannya tidak dievaluasi. & pada boolean selalu mengevaluasi kedua sisinya, dan pada bilangan bulat ia menjadi AND bitwise. Pakai && dan || untuk kondisi, terutama guard seperti user != null && user.IsActive, yang akan melempar NullReferenceException kalau memakai &.
Apa perbedaan i++ dan ++i di C#?
Keduanya menambahkan 1 ke i. Ekspresi i++ bernilai nilai lama, sedangkan ++i bernilai nilai baru. Kalau ditulis di baris tersendiri (i++;), tidak ada bedanya. Perbedaannya hanya penting saat hasilnya dipakai, seperti di int a = i++;, itulah sebabnya banyak panduan gaya menaruh increment di barisnya sendiri.
Bagaimana urutan prioritas operator di C#?
Dari yang tertinggi ke terendah: primary (x.y, f(x), a[i], x++), unary (!, -, ++x, cast), perkalian (* / %), penjumlahan (+ -), shift, relasional (< > <= >= is as), kesamaan (== !=), &, ^, |, &&, ||, ??, kondisional ?:, dan terakhir assignment. Kalau ragu, tambahkan tanda kurung.