Catatan
Akses ke halaman ini memerlukan otorisasi. Anda dapat mencoba masuk atau mengubah direktori.
Akses ke halaman ini memerlukan otorisasi. Anda dapat mencoba mengubah direktori.
C# adalah bahasa yang sangat ditik. Setiap variabel dan konstanta memiliki jenis, seperti halnya setiap ekspresi yang mengevaluasi ke nilai. Setiap deklarasi metode menentukan nama, jenis dan macam (nilai, referensi, atau output) untuk setiap parameter input dan untuk nilai yang dikembalikan. Pustaka kelas .NET mendefinisikan jenis numerik bawaan dan jenis kompleks yang mewakili berbagai konstruksi. Ini termasuk sistem file, koneksi jaringan, koleksi dan array objek, dan tanggal. Program C# umum menggunakan jenis dari pustaka kelas dan jenis yang ditentukan pengguna yang memodelkan konsep yang khusus untuk domain masalah program.
Informasi yang disimpan dalam tipe dapat menyertakan item berikut:
- Ruang penyimpanan yang diperlukan oleh variabel dari jenis tertentu.
- Nilai maksimum dan minimum yang dapat diwakilinya.
- Anggota (metode, bidang, peristiwa, dan sebagainya) yang dikandungnya.
- Tipe dasar yang diturunkan darinya.
- Antarmuka yang diimplementasikannya.
- Operasi yang diizinkan.
Pengkompilasi menggunakan informasi jenis untuk memastikan semua operasi yang dilakukan dalam kode Anda aman. Misalnya, jika Anda mendeklarasikan variabel jenis int
, pengkompilasi memungkinkan Anda untuk menggunakan variabel dalam operasi tambahan dan pengurangan. Jika Anda mencoba melakukan operasi yang sama pada variabel jenis bool
, pengkompilasi menghasilkan kesalahan, seperti yang ditunjukkan dalam contoh berikut:
int a = 5;
int b = a + 2; //OK
bool test = true;
// Error. Operator '+' cannot be applied to operands of type 'int' and 'bool'.
int c = a + test;
Nota
Pengembang C dan C++, perhatikan bahwa dalam C#, bool
tidak dapat dikonversi ke int
.
Pengkompilasi menyematkan informasi jenis ke dalam file yang dapat dieksekusi sebagai metadata. Runtime bahasa umum (CLR) menggunakan metadata tersebut pada waktu proses untuk menjamin keamanan jenis lebih lanjut saat mengalokasikan dan mengklaim kembali memori.
Menentukan jenis dalam deklarasi variabel
Ketika Anda mendeklarasikan variabel atau konstanta dalam program, Anda harus menentukan jenisnya atau menggunakan var
kata kunci untuk membiarkan pengkompilasi menyimpulkan jenisnya. Contoh berikut menunjukkan beberapa deklarasi variabel yang menggunakan jenis numerik bawaan dan jenis yang ditentukan pengguna yang kompleks:
// Declaration only:
float temperature;
string name;
MyClass myClass;
// Declaration with initializers (four examples):
char firstLetter = 'C';
var limit = 3;
int[] source = [0, 1, 2, 3, 4, 5];
var query = from item in source
where item <= limit
select item;
Jenis parameter metode dan nilai pengembalian ditentukan dalam deklarasi metode. Tanda tangan berikut menunjukkan metode yang memerlukan int
sebagai argumen input dan mengembalikan string:
public string GetName(int ID)
{
if (ID < names.Length)
return names[ID];
else
return String.Empty;
}
private string[] names = ["Spencer", "Sally", "Doug"];
Setelah mendeklarasikan variabel, Anda tidak dapat mendeklarasikannya kembali dengan jenis baru, dan Anda tidak dapat menetapkan nilai yang tidak kompatibel dengan jenis yang dideklarasikan. Misalnya, Anda tidak dapat mendeklarasikan int
dan kemudian menetapkannya nilai Boolean .true
Namun, nilai dapat dikonversi ke jenis lain, misalnya ketika ditetapkan ke variabel baru atau diteruskan sebagai argumen metode.
Konversi jenis yang tidak menyebabkan kehilangan data dilakukan secara otomatis oleh pengkompilasi. Konversi yang dapat menyebabkan kehilangan data memerlukan cast dalam kode sumber.
Untuk informasi selengkapnya, lihat Pemeran dan Konversi Jenis.
Tipe bawaan
C# menyediakan sekumpulan jenis bawaan standar. Ini mewakili bilangan bulat, nilai titik mengambang, ekspresi Boolean, karakter teks, nilai desimal, dan jenis data lainnya. Ada juga tipe bawaan string
dan object
. Jenis-jenis ini tersedia untuk Anda gunakan dalam program C# apa pun. Untuk daftar lengkap jenis bawaan, lihat Jenis bawaan.
Jenis kustom
Dengan menggunakan konstruksi struct
, class
, interface
, enum
, dan record
, Anda dapat membuat jenis kustom Anda sendiri. Pustaka kelas .NET itu sendiri adalah kumpulan jenis kustom yang dapat Anda gunakan dalam aplikasi Anda sendiri. Secara default, jenis yang paling sering digunakan di pustaka kelas tersedia dalam program C# apa pun. Yang lain hanya tersedia ketika Anda secara eksplisit menambahkan referensi proyek ke assembly yang menentukannya. Setelah pengkompilasi memiliki referensi ke rakitan, Anda dapat mendeklarasikan variabel (dan konstanta) dari jenis yang dideklarasikan dalam rakitan tersebut dalam kode sumber. Untuk informasi selengkapnya, lihat Pustaka Kelas .NET.
Salah satu keputusan pertama yang Anda buat saat menentukan jenis adalah memutuskan konstruksi mana yang akan digunakan untuk jenis Anda. Daftar berikut membantu membuat keputusan awal tersebut. Ada tumpang tindih dalam pilihan. Dalam kebanyakan skenario, lebih dari satu opsi adalah pilihan yang wajar.
- Jika ukuran penyimpanan data kecil, tidak lebih dari 64 byte, pilih
struct
ataurecord struct
. - Jika jenisnya tidak dapat diubah, atau Anda menginginkan mutasi nondestruktif, pilih
struct
ataurecord struct
. - Jika jenis Anda harus memiliki nilai semantik untuk kesetaraan, pilih
record class
ataurecord struct
. - Jika jenis terutama digunakan untuk menyimpan data, bukan perilaku, pilih
record class
ataurecord struct
. - Jika jenisnya adalah bagian dari hierarki warisan, pilih
record class
atauclass
. - Jika jenis menggunakan polimorfisme, pilih
class
. - Jika tujuan utama adalah perilaku, pilih
class
.
Sistem jenis umum
Penting untuk memahami dua poin mendasar tentang sistem jenis di .NET:
- Ini mendukung prinsip warisan. Jenis dapat berasal dari jenis lain, yang disebut jenis dasar. Jenis turunan mewarisi (dengan beberapa batasan) metode, properti, dan anggota lain dari jenis dasar. Jenis dasar pada gilirannya dapat berasal dari beberapa jenis lain, dalam hal ini jenis turunan mewarisi anggota dari kedua jenis dasar dalam hierarki warisannya. Semua jenis, termasuk jenis numerik bawaan seperti System.Int32 (kata kunci C#:
int
), pada akhirnya berasal dari satu jenis dasar, yaitu System.Object (kata kunci C#:object
). Hierarki jenis terpadu ini disebut Common Type System (CTS). Untuk informasi selengkapnya tentang pewarisan di C#, lihat Warisan. - Setiap jenis dalam CTS didefinisikan sebagai jenis nilai atau jenis referensi. Jenis ini mencakup semua jenis kustom di pustaka kelas .NET dan juga jenis yang ditentukan pengguna Anda sendiri. Jenis yang Anda tentukan dengan menggunakan
struct
kata kunci adalah jenis nilai; semua jenis numerik bawaan adalahstructs
. Jenis yang Anda tentukan dengan menggunakanclass
kata kunci ataurecord
adalah jenis referensi. Jenis referensi dan jenis nilai memiliki aturan waktu kompilasi yang berbeda, dan perilaku run-time yang berbeda.
Ilustrasi berikut menunjukkan hubungan antara jenis nilai dan jenis referensi di CTS.
Nota
Anda dapat melihat bahwa jenis yang paling umum digunakan semuanya diatur dalam System namespace. Namun, namespace di mana jenis dimuat tidak memiliki hubungan dengan apakah itu jenis nilai atau jenis referensi.
Kelas dan struktur adalah dua konstruksi dasar dari sistem jenis umum di .NET. Masing-masing pada dasarnya adalah struktur data yang merangkum sekumpulan data dan perilaku yang dimiliki bersama-sama sebagai unit logis. Data dan perilaku merupakan anggota dari kelas, struct, atau catatan. Anggota menyertakan metode, properti, peristiwa, dan sebagainya, seperti yang tercantum nanti dalam artikel ini.
Deklarasi kelas, struktur, atau rekaman seperti cetak biru yang digunakan untuk membuat instans atau objek pada waktu proses. Jika Anda menentukan kelas, struct, atau rekaman bernama Person
, Person
adalah nama jenisnya. Jika Anda mendeklarasikan dan menginisialisasi variabel p
jenis Person
, p
dikatakan sebagai objek atau instans Person
. Beberapa instans dengan jenis Person
yang sama dapat dibuat, dan setiap instans dapat memiliki nilai yang berbeda dalam properti dan bidangnya.
Kelas adalah tipe referensi. Ketika objek jenis dibuat, variabel tempat objek ditetapkan hanya menyimpan referensi ke memori tersebut. Ketika referensi objek ditetapkan ke variabel baru, variabel baru mengacu pada objek asli. Perubahan yang dilakukan melalui satu variabel tercermin dalam variabel lain karena keduanya merujuk ke data yang sama.
Struct adalah tipe data nilai. Saat sebuah struct dibuat, variabel yang dialokasikan untuk struct tersebut menyimpan data aktual dari struct itu. Saat struct ditetapkan ke variabel baru, ia disalin. Oleh karena itu, variabel baru dan variabel asli berisi dua salinan terpisah dari data yang sama. Perubahan yang dilakukan pada satu salinan tidak memengaruhi salinan lainnya.
Jenis rekaman dapat berupa jenis referensi (record class
) atau jenis nilai (record struct
). Jenis rekaman berisi metode yang mendukung kesetaraan nilai.
Secara umum, kelas digunakan untuk memodelkan perilaku yang lebih kompleks. Kelas biasanya menyimpan data yang dimaksudkan untuk dimodifikasi setelah objek kelas dibuat. Struktur paling cocok untuk struktur data kecil. Struktur biasanya menyimpan data yang tidak dimaksudkan untuk dimodifikasi setelah struktur dibuat. Jenis record adalah struktur data dengan anggota yang disintesis oleh kompilator. Rekaman biasanya menyimpan data yang tidak dimaksudkan untuk dimodifikasi setelah objek dibuat.
Jenis nilai
Jenis nilai berasal dari System.ValueType, yang berasal dari System.Object. Jenis yang berasal dari System.ValueType memiliki perilaku khusus di CLR. Variabel jenis nilai secara langsung berisi nilainya. Memori untuk struct dialokasikan secara langsung di dalam konteks apapun variabel dideklarasikan. Tidak ada alokasi tumpukan terpisah atau overhead pengumpulan sampah untuk variabel jenis nilai. Anda dapat mendeklarasikan record struct
tipe nilai dan menyertakan anggota yang disintesis untuk rekor.
Ada dua kategori jenis nilai: struct
dan enum
.
Jenis numerik bawaan adalah struktur, dan memiliki bidang dan metode yang dapat Anda akses:
// constant field on type byte.
byte b = byte.MaxValue;
Tetapi Anda mendeklarasikan dan menetapkan nilai kepada mereka seolah-olah mereka adalah jenis non-agregat sederhana:
byte num = 0xA;
int i = 5;
char c = 'Z';
Jenis nilai tertutup . Anda tidak dapat memperoleh jenis dari jenis nilai apa pun, misalnya System.Int32. Anda tidak dapat menentukan struct untuk mewarisi dari kelas atau struct yang ditentukan pengguna karena struct hanya dapat mewarisi dari System.ValueType. Namun, struct dapat mengimplementasikan satu atau beberapa antarmuka. Anda dapat mengubah tipe struct ke tipe antarmuka apa pun yang diimplementasikannya. Pemeranan ini menyebabkan operasi boxing membungkus struktur di dalam objek jenis referensi pada heap yang dikelola. Operasi tinju terjadi ketika Anda meneruskan tipe nilai ke metode yang menerima System.Object atau tipe antarmuka apa pun sebagai parameter input. Untuk informasi selengkapnya, lihat Boxing dan Unboxing.
Anda menggunakan kata kunci struktur untuk membuat jenis nilai kustom Anda sendiri. Biasanya, struct digunakan sebagai kontainer untuk sekumpulan kecil variabel terkait, seperti yang ditunjukkan dalam contoh berikut:
public struct Coords
{
public int x, y;
public Coords(int p1, int p2)
{
x = p1;
y = p2;
}
}
Untuk informasi selengkapnya tentang struktur, lihat Jenis struktur. Untuk informasi selengkapnya tentang jenis nilai, lihat Jenis nilai.
Kategori jenis nilai lainnya adalah enum
. Enum mendefinisikan sekumpulan konstanta integral bernama. Misalnya, enumerasi System.IO.FileMode di pustaka kelas .NET berisi sekumpulan bilangan bulat konstanta bernama yang menentukan bagaimana file harus dibuka. Ini didefinisikan seperti yang ditunjukkan dalam contoh berikut:
public enum FileMode
{
CreateNew = 1,
Create = 2,
Open = 3,
OpenOrCreate = 4,
Truncate = 5,
Append = 6,
}
Konstanta System.IO.FileMode.Create memiliki nilai 2. Namun, namanya jauh lebih bermakna bagi manusia yang membaca kode sumber, dan untuk alasan itu lebih baik menggunakan enumerasi alih-alih angka harfiah yang konstan. Untuk informasi selengkapnya, lihat System.IO.FileMode .
Semua enum mewarisi dari System.Enum, yang mewarisi dari System.ValueType. Semua aturan yang berlaku untuk struktur juga berlaku untuk enum. Untuk informasi selengkapnya tentang enum, lihat Jenis enumerasi.
Jenis referensi
Jenis yang didefinisikan sebagai class
, record
, delegate
, array, atau interface
adalah reference type
.
Saat Anda mendeklarasikan variabel reference type
, itu mengandung nilai null
sampai Anda menetapkannya dengan sebuah instans dari jenis tersebut atau membuatnya menggunakan operator new
. Pembuatan dan penugasan kelas ditunjukkan dalam contoh berikut:
MyClass myClass = new MyClass();
MyClass myClass2 = myClass;
Suatu interface
tidak dapat langsung diinstansiasi dengan menggunakan operator new
. Sebagai gantinya, buat dan tetapkan instans kelas yang mengimplementasikan antarmuka. Pertimbangkan contoh berikut:
MyClass myClass = new MyClass();
// Declare and assign using an existing value.
IMyInterface myInterface = myClass;
// Or create and assign a value in a single statement.
IMyInterface myInterface2 = new MyClass();
Ketika objek dibuat, memori dialokasikan pada tumpukan terkelola. Variabel hanya menyimpan referensi ke lokasi objek. Jenis pada tumpukan terkelola memerlukan overhead baik saat dialokasikan maupun saat diambil kembali. Pengumpulan sampah adalah fungsionalitas manajemen memori otomatis CLR, yang melakukan reklamasi. Namun, pengumpulan sampah juga sangat dioptimalkan, dan dalam sebagian besar skenario tidak menciptakan masalah performa. Untuk informasi selengkapnya tentang pengumpulan sampah, lihat Manajemen Memori Otomatis.
Semua array adalah jenis referensi, bahkan jika elemennya adalah jenis nilai. Arrays secara implisit berasal dari kelas System.Array. Anda mendeklarasikan dan menggunakannya dengan sintaks yang disederhanakan yang disediakan oleh C#, seperti yang ditunjukkan dalam contoh berikut:
// Declare and initialize an array of integers.
int[] nums = [1, 2, 3, 4, 5];
// Access an instance property of System.Array.
int len = nums.Length;
Jenis referensi sepenuhnya mendukung pewarisan. Saat Anda membuat kelas, Anda dapat mewarisi dari antarmuka atau kelas lain yang tidak didefinisikan sebagai tertutup. Kelas lain dapat mewarisi dari kelas Anda dan mengambil alih metode virtual Anda. Untuk informasi selengkapnya tentang cara membuat kelas Anda sendiri, lihat Kelas, struktur, dan rekaman. Untuk informasi selengkapnya tentang pewarisan dan metode virtual, lihat Warisan.
Jenis nilai harfiah
Di C#, nilai harfiah menerima jenis dari pengkompilasi. Anda dapat menentukan bagaimana harfiah numerik harus di ketik dengan menambahkan huruf ke akhir angka. Misalnya, untuk menentukan bahwa nilai 4.56
harus diperlakukan sebagai float
, tambahkan "f" atau "F" setelah angka: 4.56f
. Jika tidak ada karakter yang ditambahkan, pengompilasi menyimpulkan tipe untuk literal. Untuk informasi lebih lanjut tentang tipe mana yang dapat ditentukan dengan akhiran huruf, lihat Jenis numerik integral dan Jenis numerik titik mengambang.
Karena literal ditik, dan semua jenis pada akhirnya berasal dari System.Object, Anda dapat menulis dan mengkompilasi kode seperti kode berikut:
string s = "The answer is " + 5.ToString();
// Outputs: "The answer is 5"
Console.WriteLine(s);
Type type = 12345.GetType();
// Outputs: "System.Int32"
Console.WriteLine(type);
Tipe Generik
Jenis dapat dideklarasikan dengan satu atau beberapa parameter jenis yang berfungsi sebagai placeholder untuk jenis aktual (jenis konkret). Kode klien menyediakan jenis konkret saat menciptakan instance dari jenis tersebut. Jenis tersebut disebut jenis generik. Misalnya, jenis System.Collections.Generic.List<T> .NET memiliki satu parameter jenis yang menurut konvensi diberi nama T
. Saat Anda membuat instans dari tipe tersebut, Anda menentukan tipe objek yang dimiliki oleh daftar, misalnya, string
:
List<string> stringList = new List<string>();
stringList.Add("String example");
// compile time error adding a type other than a string:
stringList.Add(4);
Penggunaan parameter jenis memungkinkan untuk menggunakan kembali kelas yang sama untuk menyimpan semua jenis elemen, tanpa harus mengonversi setiap elemen menjadi objek. Kelas koleksi generik disebut koleksi yang ditik dengan kuat karena pengkompilasi mengetahui jenis elemen koleksi tertentu dan dapat menimbulkan kesalahan pada waktu kompilasi jika, misalnya, Anda mencoba menambahkan bilangan bulat ke stringList
objek dalam contoh sebelumnya. Untuk informasi selengkapnya, lihat Generik.
Jenis implisit, jenis anonim, dan jenis tipe nilai dapat null
Anda dapat mengetik variabel lokal secara implisit (tetapi bukan anggota kelas) dengan menggunakan var
kata kunci. Variabel masih menerima jenis pada waktu kompilasi, tetapi jenisnya disediakan oleh pengkompilasi. Untuk informasi selengkapnya, lihat Variabel Lokal Berjenis Implisit.
Mungkin kurang praktis untuk membuat tipe bernama untuk kelompok nilai terkait yang sederhana yang tidak Anda rencanakan untuk disimpan atau diteruskan di luar batasan metode. Anda dapat membuat jenis anonim untuk tujuan ini. Untuk informasi selengkapnya, lihat Jenis Anonim.
Jenis nilai biasa tidak dapat memiliki nilai null
. Namun, Anda dapat membuat tipe nilai nullable dengan menambahkan ?
setelah tipe. Misalnya, int?
adalah int
jenis yang juga dapat memiliki nilai null
. Tipe nilai nullable adalah instans dari tipe generik System.Nullable<T> struct. Jenis nilai nullable sangat berguna ketika Anda meneruskan data ke dan dari database yang mungkin memiliki nilai numerik null
. Untuk informasi selengkapnya, lihat Jenis nilai nullable.
Jenis waktu kompilasi dan jenis waktu jalan
Variabel dapat memiliki jenis waktu kompilasi dan run-time yang berbeda. Jenis waktu kompilasi adalah jenis variabel yang dideklarasikan atau disimpulkan dalam kode sumber. Tipe saat berjalan adalah tipe dari instance yang dikaitkan dengan variabel tersebut. Seringkali kedua jenis tersebut sama, seperti dalam contoh berikut:
string message = "This is a string of characters";
Dalam kasus lain, jenis waktu kompilasi berbeda, seperti yang ditunjukkan dalam dua contoh berikut:
object anotherMessage = "This is another string of characters";
IEnumerable<char> someCharacters = "abcdefghijklmnopqrstuvwxyz";
Dalam kedua contoh sebelumnya, jenis run-time adalah string
. Jenis waktu kompilasi berada object
di baris pertama, dan IEnumerable<char>
di baris kedua.
Jika kedua jenis berbeda untuk variabel, penting untuk dipahami ketika jenis waktu kompilasi dan jenis run-time berlaku. Jenis waktu kompilasi menentukan semua tindakan yang diambil oleh pengkompilasi. Tindakan pengkompilasi ini mencakup resolusi panggilan metode, resolusi kelebihan beban, dan pemeran implisit dan eksplisit yang tersedia. Jenis run-time menentukan semua tindakan yang diselesaikan pada waktu proses. Tindakan run-time ini mencakup pengiriman panggilan metode virtual, evaluasi is
dan switch
ekspresi, dan API pengujian jenis lainnya. Untuk lebih memahami bagaimana kode Anda berinteraksi dengan jenis, kenali tindakan mana yang berlaku untuk jenis mana.
Bagian terkait
Untuk informasi lebih lanjut, baca artikel berikut:
Spesifikasi bahasa C#
Untuk informasi selengkapnya, lihat Spesifikasi Bahasa C#. Spesifikasi bahasa adalah sumber definitif untuk sintaks dan penggunaan C#.