C# bertipe statis: setiap variabel, field, dan ekspresi punya tipe yang sudah diketahui saat compile. Bahasa ini punya sekumpulan tipe bawaan dengan keyword-nya sendiri (int, double, string...). Setiap keyword adalah alias untuk sebuah tipe di namespace System, jadi int dan System.Int32 adalah tipe yang sama, begitu juga string dan System.String.
Tipe bawaan
| Tipe | Tipe .NET | Ukuran | Rentang atau presisi | Literal |
|---|---|---|---|---|
bool | Boolean | 1 byte | true atau false | true |
byte | Byte | 1 byte | 0 sampai 255 | 200 |
sbyte | SByte | 1 byte | -128 sampai 127 | -5 |
short | Int16 | 2 byte | -32.768 sampai 32.767 | 1200 |
ushort | UInt16 | 2 byte | 0 sampai 65.535 | 60000 |
int | Int32 | 4 byte | -2.147.483.648 sampai 2.147.483.647 | 42 |
uint | UInt32 | 4 byte | 0 sampai 4.294.967.295 | 42u |
long | Int64 | 8 byte | sekitar ±9,2 × 10^18 | 42L |
ulong | UInt64 | 8 byte | 0 sampai sekitar 1,8 × 10^19 | 42ul |
float | Single | 4 byte | sekitar ±3,4 × 10^38, ~6 sampai 9 digit | 2.5f |
double | Double | 8 byte | sekitar ±1,8 × 10^308, ~15 sampai 17 digit | 2.5 atau 2.5d |
decimal | Decimal | 16 byte | sekitar ±7,9 × 10^28, 28 sampai 29 digit | 2.5m |
char | Char | 2 byte | satu code unit UTF-16, U+0000 sampai U+FFFF | 'A' |
string | String | reference | teks sepanjang apa pun, immutable | "hello" |
object | Object | reference | dasar dari setiap tipe | new object() |
Literal integer tanpa suffix bertipe int, atau tipe pertama di antara uint, long, dan ulong yang bisa menampungnya kalau terlalu besar untuk int, dan literal dengan titik desimal bertipe double. Itulah sebabnya float f = 2.5; dan decimal d = 2.5; gagal di-compile: literalnya bertipe double, dan tidak ada konversi implisit dari double ke float atau decimal. Tambahkan suffix-nya: 2.5f, 2.5m.
Setiap tipe numerik menyediakan batas-batasnya sebagai konstanta:
Output:
byte: 0 to 255
short: -32768 to 32767
int: -2147483648 to 2147483647
long: -9223372036854775808 to 9223372036854775807
decimal max: 79228162514264337593543950335
double max: 1.798E+308
sizes: int 4, long 8, double 8, char 2
255 161 3000000000
Dalam praktiknya, sebagian besar kode memakai empat tipe ini: int untuk hitungan dan index, long untuk ID dan total yang besar, double untuk pengukuran dan matematika, dan decimal untuk uang.
decimal vs double
double (dan float) menyimpan angka dalam bentuk biner. Sebagian besar pecahan desimal, termasuk 0,1, tidak punya bentuk biner yang tepat, jadi disimpan sebagai nilai terdekat yang bisa direpresentasikan, dan kesalahan kecil menumpuk. decimal menyimpan integer basis 10 ditambah skala, jadi 0,1 benar-benar 0,1.
Output:
False
True
0.30000000000000004
0.3
double sum == 1.0: False
decimal sum == 1.0: True
Total: 59.97
Split three ways: 19.99
Pakai decimal untuk uang, harga, pajak, dan apa pun yang akan dijumlahkan dan dibandingkan oleh manusia secara manual. Tipe ini mempertahankan nol di belakang dari input-nya (1.50m dicetak sebagai 1.50) dan punya 28 sampai 29 digit signifikan.
Pakai double untuk pengukuran fisik, statistik, geometri, dan game. Tipe ini beberapa kali lebih cepat, memakai setengah memori, dan rentangnya sangat besar. Jangan pernah membandingkan dua double hasil perhitungan dengan ==; bandingkan selisihnya dengan toleransi: Math.Abs(x - y) < 1e-9.
decimal bukan sulap: 1m / 3m tetap menghasilkan 0.3333333333333333333333333333, dan aritmetika double tidak melempar exception saat dibagi nol (hasilnya infinity, atau NaN untuk 0.0 / 0.0), sedangkan pembagian dengan nol pada decimal dan integer melempar DivideByZeroException.
Integer overflow dan checked
Aritmetika integer yang melebihi rentang tipenya secara default akan berputar balik, tanpa peringatan. Compiler menangkap overflow di ekspresi konstanta, tetapi tidak saat nilainya berasal dari variabel:
Output:
-2147483648
OverflowException
-1294967296
2147483648
checked(...) atau blok checked { ... } mengubah overflow menjadi OverflowException. Kamu juga bisa mengaktifkannya untuk seluruh project dengan <CheckForOverflowUnderflow>true</CheckForOverflowUnderflow>. Menulis int x = int.MaxValue + 1; dengan konstanta menghasilkan error compile (CS0220), karena compiler bisa melihat overflow-nya.
Baris terakhir menunjukkan solusi untuk sebagian besar bug overflow: konversi ke tipe yang lebih lebar sebelum aritmetikanya. (long)(max + 1) akan salah, karena penjumlahannya sudah berputar balik saat cast dijalankan.
Tipe value dan tipe reference
Setiap tipe C# adalah tipe value atau tipe reference, dan perbedaannya menentukan apa yang dilakukan assignment.
- Tipe value: semua tipe numerik,
bool,char,DateTime, enum, dan setiapstruct. Variabelnya berisi data itu sendiri; assignment menyalinnya. - Tipe reference:
string, array,object, dan setiapclass. Variabelnya berisi reference ke sebuah object; assignment menyalin reference-nya, jadi kedua variabel melihat object yang sama.
Output:
a=10 b=99
first[0]=99
s1=cat s2=cats
string adalah tipe reference yang dalam praktiknya berperilaku seperti value: string bersifat immutable, dan == membandingkan teksnya, bukan reference-nya. Selengkapnya tentang tipe value buatan sendiri ada di struct.
char dan bool
char adalah satu code unit UTF-16, ditulis di antara tanda kutip tunggal. Di baliknya, tipe ini adalah tipe numerik, jadi bisa dikonversi ke int dan mendukung aritmetika:
Output:
66
C
True
True
7
b
True
bool punya tepat dua nilai dan tidak bisa dikonversi dari atau ke angka: if (count) menghasilkan error compile, bukan pengecekan bukan-nol. Tulis if (count != 0). Karakter di luar Basic Multilingual Plane, seperti kebanyakan emoji, memakai dua nilai char (surrogate pair), jadi Length pada string menghitung unit UTF-16, bukan karakter yang terlihat.
Nilai default
Field, elemen array, dan default(T) mendapat nilai default tipenya: nol untuk angka, false untuk bool, '\0' untuk char, dan null untuk tipe reference. Variabel lokal tidak mendapat nilai default dan harus di-assign sebelum dipakai.
Output:
0
0
False
True
0001-01-01
0,0,0
Sejak C# 7.1, kamu bisa menulis literal default tanpa tipenya saat compiler bisa menyimpulkannya (int x = default;). Tipe value tidak bisa bernilai null, dan untuk itulah ada int? (nullable value type); lihat nullable type.
Integer seukuran native dan integer besar
Ada dua tipe numerik lagi untuk kasus khusus. nint dan nuint (C# 9) adalah integer seukuran pointer, 32 atau 64 bit tergantung platformnya, dipakai di interop dan kode tingkat rendah. System.Numerics.BigInteger menyimpan integer dengan ukuran berapa pun, dengan mengorbankan kecepatan:
using System.Numerics;
BigInteger factorial = 1;
for (int i = 2; i <= 30; i++) factorial *= i;
// 265252859812191058636308480000000
Pertanyaan yang sering diajukan
Apa saja tipe data di C#?
Tipe bawaannya adalah tipe integer (sbyte, byte, short, ushort, int, uint, long, ulong), tipe floating-point float dan double, decimal untuk aritmetika desimal yang tepat, char untuk satu karakter UTF-16, bool, serta tipe reference string dan object. Setiap keyword adalah alias untuk sebuah tipe .NET: int adalah System.Int32, string adalah System.String.
Sebaiknya pakai decimal atau double untuk uang di C#?
Pakai decimal. double menyimpan pecahan biner, jadi nilai seperti 0,1 tidak bisa direpresentasikan dengan tepat dan hasil penjumlahannya bergeser (0.1 + 0.2 == 0.3 bernilai false). decimal menyimpan digit basis 10, mempertahankan 28 sampai 29 digit signifikan, dan memberi hasil yang diharapkan akuntan. double lebih cepat dan rentangnya jauh lebih besar, jadi pakai untuk sains, grafis, dan pengukuran.
Berapa nilai maksimum int di C#?
int.MaxValue adalah 2.147.483.647 dan int.MinValue adalah -2.147.483.648 (integer signed 32-bit). Menambahkan 1 ke int.MaxValue diam-diam berputar menjadi int.MinValue, kecuali kodenya berjalan di context checked, yang akan melempar OverflowException. Pakai long (sampai sekitar 9,2 × 10^18) untuk nilai yang lebih besar.
Apa bedanya float dan double di C#?
float berukuran 32 bit dengan sekitar 6 sampai 9 digit signifikan; double berukuran 64 bit dengan sekitar 15 sampai 17 digit. Literal floating-point secara default bertipe double, jadi float butuh suffix f: float speed = 2.5f;. Pakai double kecuali memori atau sebuah API (seperti Vector3 di Unity) membutuhkan float.
Apa bedanya tipe value dan tipe reference di C#?
Variabel bertipe value (int, double, bool, DateTime, struct apa pun) menyimpan datanya sendiri, dan assignment menyalinnya. Variabel bertipe reference (string, array, class apa pun) menyimpan reference ke object di heap, dan assignment menyalin reference-nya, jadi dua variabel bisa menunjuk ke object yang sama.