Tur bahasa C#

C# (dibaca "See Sharp") adalah bahasa pemrograman jenis-aman modern dan berorientasi-objek. C# memungkinkan pengembang untuk membangun banyak jenis aplikasi yang aman dan kuat yang berjalan di .NET. C# memiliki akar dalam keluarga bahasa C dan akan segera dikenal oleh programer C, C++, Java, dan JavaScript. Tur ini memberikan gambaran umum tentang komponen utama bahasa dalam C# 8 dan yang lebih lama. Jika Anda ingin menjelajahi bahasa melalui contoh interaktif, coba tutorial pengenalan C#.

C# adalah bahasa pemrograman berorientasi objek dan berorientasi komponen. C# menyediakan konstruksi bahasa untuk secara langsung mendukung konsep-konsep ini, menjadikan C# bahasa alami untuk membuat dan menggunakan komponen perangkat lunak. Sejak awal, C# telah menambahkan fitur untuk mendukung beban kerja baru dan praktik desain perangkat lunak yang muncul. Pada intinya, C# adalah bahasa berorientasi objek. Anda menentukan jenis dan perilakunya.

Beberapa fitur C# membantu menciptakan aplikasi yang kuat dan tahan lama. Pengumpulan sampah secara otomatis mengklaim kembali memori yang ditempati oleh objek yang tidak dapat dijangkau dan tidak gunakan. Jenis yang dapat diubah ke null mengawal dari variabel yang tidak merujuk ke objek yang dialokasikan. Penanganan pengecualian menyediakan pendekatan terstruktur dan dapat diperluas untuk deteksi dan pemulihan kesalahan. Ekspresi Lambda mendukung teknik pemrograman fungsi. Sintaks Language Integrated Query (LINQ) membuat pola umum untuk bekerja dengan data dari sumber apa pun. Dukungan bahasa untuk operasi asinkron menyediakan sintaks untuk membangun sistem terdistribusi. C# memiliki sistem jenis terpadu. Semua jenis C#, termasuk jenis primitif seperti int dan double, mewarisi dari satu jenis akar object. Semua jenis berbagi serangkaian operasi umum. Nilai jenis apa pun dapat disimpan, diangkut, dan dioperasikan secara konsisten. Selain itu, C# mendukung jenis referensi dan jenis nilai yang ditentukan pengguna. C# memungkinkan alokasi objek dinamis dan penyimpanan in-line struktur ringan. C# mendukung metode dan jenis generik, yang memberikan peningkatan keamanan dan performa jenis. C# menyediakan iterator, yang memungkinkan pelaksana kelas koleksi untuk menentukan perilaku kustom untuk kode klien.

C# menekankan penerapan versi untuk memastikan program dan pustaka dapat berkembang dari waktu ke waktu dengan cara yang kompatibel. Aspek desain C#yang secara langsung dipengaruhi oleh pertimbangan penerapan versi termasuk pengubah virtual dan override yang terpisah, aturan untuk resolusi kelebihan beban metode, dan dukungan untuk deklarasi anggota antarmuka eksplisit.

Arsitektur .NET

Program C# berjalan pada .NET, sistem eksekusi virtual yang disebut runtime bahasa umum (CLR) dan satu set pustaka kelas. CLR adalah implementasi oleh Microsoft dari infrastruktur bahasa umum (CLI), standar internasional. CLI adalah dasar untuk membuat lingkungan eksekusi dan pengembangan di mana bahasa dan pustaka bekerja sama dengan lancar.

Kode sumber yang ditulis dalam C# dikompilasi ke dalam bahasa perantara (IL) yang sesuai dengan spesifikasi CLI. Kode IL dan sumber daya, seperti bitmap dan string, disimpan dalam rakitan, biasanya dengan ekstensi .dll. Rakitan berisi manifes yang menyediakan informasi tentang jenis, versi, dan budaya perakitan.

Ketika program C# dijalankan, rakitan dimuat ke dalam CLR. CLR melakukan kompilasi Just-In-Time (JIT) untuk mengonversi kode IL ke instruksi komputer asli. CLR menyediakan layanan lain yang terkait dengan pengumpulan sampah otomatis, penanganan pengecualian, dan manajemen sumber daya. Kode yang dijalankan oleh CLR terkadang disebut sebagai "kode terkelola." "Kode tidak terkelola," dikompilasi ke dalam bahasa komputer asli yang menargetkan platform tertentu.

Interoperabilitas bahasa adalah fitur utama .NET. Kode IL yang diproduksi oleh pengkompilasi C# sesuai dengan Spesifikasi Jenis Umum (CTS). Kode IL yang dihasilkan dari C# dapat berinteraksi dengan kode yang dihasilkan dari versi .NET F#, Visual Basic, C++. Ada lebih dari 20 bahasa lain yang patuh-CTS. Satu rakitan mungkin berisi beberapa modul yang ditulis dalam bahasa .NET yang berbeda. Jenis dapat saling mereferensikan seolah-olah mereka ditulis dalam bahasa yang sama.

Selain layanan run time, .NET juga mencakup pustaka yang luas. Pustaka ini mendukung banyak beban kerja yang berbeda. Mereka diatur ke dalam namespace layanan yang menyediakan berbagai fungsionalitas yang berguna. Pustaka mencakup semua hal mulai dari input file dan output hingga manipulasi string ke penguraian XML, hingga kerangka kerja aplikasi web hingga kontrol Formulir Windows. Aplikasi C# yang khas menggunakan pustaka kelas .NET secara ekstensif untuk menangani tugas "penyaluran" umum.

Untuk informasi selengkapnya tentang .NET, lihat Gambaran umum .NET.

Halo-dunia

Program "Halo, Dunia" secara tradisional digunakan untuk memperkenalkan bahasa pemrograman. Di sini ada di C#:

using System;

class Hello
{
    static void Main()
    {
        Console.WriteLine("Hello, World");
    }
}

Program "Halo, Dunia" dimulai dengan arahan using yang mereferensikan namespace System. Namespace menyediakan cara hierarkis untuk mengatur program dan pustaka C#. Namespace berisi jenis dan namespace lainnya—misalnya, namespace System berisi sejumlah jenis, seperti kelas Console yang dirujuk dalam program, dan sejumlah namespace lainnya, seperti IO dan Collections. Arahan using yang mereferensikan namespace layanan tertentu memungkinkan penggunaan yang tidak memenuhi syarat dari jenis yang merupakan anggota namespace tersebut. Karena direktif using, program dapat menggunakan Console.WriteLine sebagai singkatan untuk System.Console.WriteLine.

Kelas Hello yang dideklarasikan oleh program "Halo, Dunia" memiliki satu anggota, metode bernama Main. Metode Main ini dideklarasikan dengan pengubah static. Meskipun metode instans dapat mereferensikan instans objek penutup tertentu menggunakan kata kunci this, metode statis beroperasi tanpa mereferensikan ke objek tertentu. Menurut konvensi, metode statis bernama Main berfungsi sebagai titik masuk program C#.

Output program dihasilkan oleh metode WriteLine dari kelas Console di namespace layanan System. Kelas ini disediakan oleh pustaka kelas standar, yang, secara default, direferensikan secara otomatis oleh pengkompilasi.

Jenis dan variabel

Jenis menentukan struktur dan perilaku data apa pun dalam C#. Deklarasi jenis dapat mencakup anggotanya, jenis dasar, antarmuka yang diterapkannya, dan operasi yang diizinkan untuk jenis tersebut. Variabel adalah label yang mengacu pada instans jenis tertentu.

Ada dua macam jenis dalam C #: jenis nilai dan jenis referensi. Variabel jenis nilai secara langsung berisi datanya. Variabel jenis referensi menyimpan referensi untuk data itu, data itu dikenal sebagai objek. Dengan jenis referensi, dimungkinkan bagi dua variabel untuk mereferensikan objek yang sama dan memungkinkan operasi pada satu variabel memengaruhi objek yang dirujuk oleh variabel lain. Dengan jenis nilai, variabel masing-masing memiliki salinan data mereka sendiri, dan tidak mungkin bagi operasi pada satu data untuk memengaruhi data yang lain (kecuali untuk variabel parameter ref dan out).

Pengidentifikasi adalah nama variabel. Pengidentifikasi adalah urutan karakter unicode tanpa spasi kosong. Pengidentifikasi mungkin merupakan kata cadangan C#, jika diawali oleh @. Menggunakan kata cadangan sebagai pengidentifikasi dapat berguna saat berinteraksi dengan bahasa lain.

Jenis nilai C# selanjutnya dibagi menjadi jenis sederhana, jenis enum, jenis struct, jenis nilai nullable, dan jenis nilai tuple. Jenis referensi C# dibagi lebih lanjut menjadi jenis kelas, jenis antarmuka, jenis array, dan jenis delegasi.

Kerangka berikut ini memberikan gambaran umum tentang sistem jenis C#.

Program C# menggunakan deklarasi jenis untuk membuat jensi baru. Deklarasi jenis menentukan nama dan anggota jenis baru. Enam dari kategori jenis C# dapat didefinisikan pengguna: jenis kelas, jenis struct, jenis antarmuka, jenis enum, jenis delegasi, dan jenis nilai tuple. Anda juga dapat mendeklarasikan jenis record, baik record struct, atau record class. Jenis rekaman memiliki anggota yang disintesis-pengkompilasi. Anda menggunakan rekaman terutama untuk menyimpan nilai, dengan perilaku terkait minimal.

  • Jenis class menentukan struktur data yang berisi anggota data (bidang) dan anggota fungsi (metode, properti, dan lainnya). Jenis kelas mendukung pewarisan tunggal dan polimorfisme, mekanisme di mana kelas turunan dapat memperluas dan mengkhususkan kelas dasar.
  • Jenis struct mirip dengan jenis kelas karena mewakili struktur dengan anggota data dan anggota fungsi. Namun, berbeda dengan kelas, struktur adalah jenis nilai dan biasanya tidak memerlukan alokasi timbunan. Jenis struct tidak mendukung pewarisan yang ditentukan pengguna, dan semua jenis struct secara implisit mewarisi dari jenis object.
  • Jenis interface mendefinisikan kontrak sebagai sekumpulan anggota publik bernama. class atau struct yang mengimplementasikan interface harus menyediakan implementasi anggota antarmuka. interface bisa mewarisi dari beberapa antarmuka dasar, dan satu class atau struct dapat mengimplementasikan beberapa antarmuka.
  • Jenis delegate mewakili referensi ke metode dengan daftar parameter dan jenis pengembalian tertentu. Delegasi memungkinkan untuk memperlakukan metode sebagai entitas yang dapat ditetapkan ke variabel dan diteruskan sebagai parameter. Delegasi sama dengan jenis fungsi yang disediakan oleh bahasa fungsi. Delegasi juga mirip dengan konsep pointer fungsi yang ditemukan di beberapa bahasa lain. Tidak seperti pointer fungsi, delegasi berorientasi-objek dan aman-jenis.

Jenis class, struct, interface, dan delegate semua mendukung generik, yang dapat diparameterkan dengan jenis lain.

C# mendukung array dimensi tunggal dan multidimensi dari jenis apa pun. Tidak seperti jenis yang tercantum di atas, jenis array tidak harus dideklarasikan sebelum dapat digunakan. Sebaliknya, jenis array dibangun dengan mengikuti nama jenis dengan tanda kurung siku. Misalnya, int[] adalah array dimensi tunggal dari int, int[,] adalah array dua dimensi dari int, dan int[][] merupakan array dimensi tunggal dari array dimensi tunggal, atau array "jagged", dari int.

Jenis yang dapat diubah ke null tidak memerlukan definisi terpisah. Untuk setiap jenis Tyang tidak dapat diubah ke null, ada jenis yang dinolkan T? yang sesuai, yang dapat menyimpan nilai tambahan, null. Misalnya, int? adalah jenis yang dapat menampung bilangan bulat 32-bit atau nilai null, dan string? merupakan jenis yang dapat menampung salah satu string atau nilai null.

Sistem jenis C# disatukan sehingga nilai jenis apa pun dapat diperlakukan sebagai object. Setiap jenis dalam C# secara langsung atau tidak langsung berasal dari jenis kelas object, dan object merupakan kelas dasar utama dari semua jenis. Nilai jenis referensi diperlakukan sebagai objek hanya dengan melihat nilai sebagai jenis object. Nilai dari jenis nilai diperlakukan sebagai objek dengan melakukan operasi mengemas dan membuka kemasan. Dalam contoh berikut, nilai int dikonversi ke object dan kembali lagi ke int.

int i = 123;
object o = i;    // Boxing
int j = (int)o;  // Unboxing

Saat nilai jenis nilai ditetapkan ke referensi object, "kotak" kemasan ditempatkan untuk menampung nilai itu. Kotak itu adalah instans jenis referensi, dan nilainya disalin ke dalam kotak tersebut. Sebaliknya, saat referensi object dilemparkan ke jenis nilai, pengecekan dilakukan apakah object yang direferensikan adalah kotak jenis nilai yang benar. Jika pemeriksaan berhasil, nilai dalam kotak disalin ke jenis nilai.

Sistem jenis terpadu C# secara efektif berarti bahwa jenis nilai diperlakukan sebagai referensi object "sesuai permintaan." Karena penyatuan, pustaka tujuan umum yang menggunakan jenis object dapat digunakan dengan semua jenis yang berasal dari object, termasuk jenis referensi dan jenis nilai.

Ada beberapa jenis variabel dalam C#, termasuk bidang, elemen array, variabel lokal, dan parameter. Variabel mewakili lokasi penyimpanan. Setiap variabel memiliki jenis yang menentukan nilai apa yang dapat disimpan dalam variabel, seperti yang ditunjukkan di bawah ini.

  • Jenis nilai yang tidak dapat diubah ke null
    • Nilai dari jenis yang tepat
  • Jenis nilai yang dapat diubah ke null
    • Nilai null atau nilai dari jenis yang tepat
  • objek
    • Referensi null, referensi ke objek dari jenis referensi apa pun, atau referensi ke nilai berkotak dari jenis nilai apa pun
  • Jenis kelas
    • Referensi null, referensi ke instans jenis kelas tersebut, atau referensi ke instans kelas yang berasal dari jenis kelas tersebut
  • Jenis antarmuka
    • Referensi null, referensi ke instans jenis kelas yang mengimplementasikan jenis antarmuka tersebut, atau referensi ke nilai kotak dari jenis nilai yang mengimplementasikan jenis antarmuka tersebut
  • Jenis Array
    • Referensi null, referensi ke instans jenis array tersebut, atau referensi ke instans jenis array yang kompatibel
  • Jenis delegasi
    • Referensi null atau referensi ke instans jenis delegasi yang kompatibel

Struktur program

Konsep organisasi utama dalam C# adalah program, namespace, jenis, anggota, dan rakitan. Program mendeklarasikan jenis, yang berisi anggota dan dapat diatur ke dalam namespace. Kelas, struktur, dan antarmuka adalah contoh jenisnya. Bidang, metode, properti, dan peristiwa adalah contoh anggota. Ketika program C# dikompilasi, program tersebut dikemas secara fisik ke dalam rakitan. Rakitan biasanya memiliki ekstensi file .exe atau .dll, tergantung pada apakah mereka menerapkan aplikasi atau pustaka.

Sebagai contoh kecil, pertimbangkan perakitan yang berisi kode berikut:

namespace Acme.Collections;

public class Stack<T>
{
    Entry _top;

    public void Push(T data)
    {
        _top = new Entry(_top, data);
    }

    public T Pop()
    {
        if (_top == null)
        {
            throw new InvalidOperationException();
        }
        T result = _top.Data;
        _top = _top.Next;

        return result;
    }

    class Entry
    {
        public Entry Next { get; set; }
        public T Data { get; set; }

        public Entry(Entry next, T data)
        {
            Next = next;
            Data = data;
        }
    }
}

Nama yang sepenuhnya memenuhi syarat dari kelas ini adalah Acme.Collections.Stack. Kelas berisi beberapa anggota: bidang bernama _top, dua metode bernama Push dan Pop, dan kelas berlapis bernama Entry. Kelas Entry selanjutnya berisi tiga anggota: properti bernama Next, properti bernama Data, dan konstruktor. Stack adalah kelas generik. Kelas tersebut memiliki satu jenis parameter, T yang diganti dengan jenis yang konkret saat digunakan.

Tumpukan adalah koleksi "pertama masuk - terakhir keluar" (FILO, first in - last out). Elemen baru ditambahkan ke bagian atas tumpukan. Saat elemen dihapus, elemen akan dihapus dari bagian atas tumpukan. Contoh sebelumnya mendeklarasikan jenis Stack yang menentukan penyimpanan dan perilaku untuk tumpukan. Anda dapat mendeklarasikan variabel yang mengacu pada instans jenis Stack untuk menggunakan fungsionalitas tersebut.

Rakitan berisi kode yang dapat dieksekusi dalam bentuk instruksi Bahasa Perantara (IL), dan informasi simbolis dalam bentuk metadata. Sebelum dijalankan, pengkompilasi Just-In-Time (JIT) dari .NET Common Language Runtime mengonversi kode IL dalam perakitan menjadi kode khusus prosesor.

Karena raskitan adalah unit fungsionalitas yang menjelaskan-sendiri yang berisi kode dan metadata, tidak perlu ada direktif #include dan file header di C#. Jenis publik dan anggota yang terdapat dalam rakitan tertentu tersedia dalam program C# hanya dengan merujuk perakitan tersebut saat mengkompilasi program. Misalnya, program ini menggunakan kelas Acme.Collections.Stack dari rakitan acme.dll:

class Example
{
    public static void Main()
    {
        var s = new Acme.Collections.Stack<int>();
        s.Push(1); // stack contains 1
        s.Push(10); // stack contains 1, 10
        s.Push(100); // stack contains 1, 10, 100
        Console.WriteLine(s.Pop()); // stack contains 1, 10
        Console.WriteLine(s.Pop()); // stack contains 1
        Console.WriteLine(s.Pop()); // stack is empty
    }
}

Untuk mengkompilasi program ini, Anda perlu mereferensikan rakitan yang berisi kelas tumpukan yang ditentukan dalam contoh sebelumnya.

Program C# dapat disimpan dalam beberapa file sumber. Ketika program C# dikompilasi, semua file sumber diproses bersama-sama, dan file sumber dapat secara bebas saling mereferensikan. Secara konseptual, seolah-olah semua file sumber digabungkan menjadi satu file besar sebelum diproses. Deklarasi penerusan tidak pernah diperlukan dalam C# karena, dengan beberapa pengecualian, urutan deklarasi tidak signifikan. C# tidak membatasi file sumber untuk mendeklarasikan hanya satu jenis publik atau tidak memerlukan nama file sumber untuk mencocokkan jenis yang dideklarasikan dalam file sumber.

Artikel selanjutnya dalam tur ini menjelaskan blok organisasi ini.