Jenis referensi bawaan (referensi C#)

C# memiliki banyak jenis referensi bawaan. Mereka memiliki kata kunci atau operator yang sinonim untuk jenis di perpustakaan .NET.

Jenis objek

Jenisnya object adalah alias untuk System.Object di .NET. Dalam sistem jenis terpadu C#, semua jenis, yang telah ditentukan dan ditentukan pengguna, jenis referensi dan jenis nilai, mewarisi secara langsung atau tidak langsung dari System.Object. Anda dapat menetapkan nilai dari jenis apa pun ke variabel jenis object. Variabel object apa pun dapat ditetapkan ke nilai defaultnya menggunakan null harfiah. Saat variabel dari jenis nilai dikonversi ke objek, variabel tersebut dikatakan dimasukkan dalam kotak. Saat variabel jenis object dikonversi ke jenis nilai, variabel tersebut dikatakan tidak dimasukkan dalam kotak. Untuk informasi selengkapnya, lihat Pengkotakan dan Pembukaan Kotak.

Jenis String

Jenis string ini mewakili urutan nol atau lebih karakter Unicode. string adalah alias untuk System.String dalam .NET.

Meskipun string merupakan jenis referensi, operator kesetaraan == dan != didefinisikan untuk membandingkan nilai objek string, bukan referensi. Kesetaraan berbasis nilai membuat pengujian untuk kesetaraan string lebih intuitif. Contohnya:

string a = "hello";
string b = "h";
// Append to contents of 'b'
b += "ello";
Console.WriteLine(a == b);
Console.WriteLine(object.ReferenceEquals(a, b));

Contoh sebelumnya menampilkan "True" lalu "False" karena konten string setara, tetapi a dan b tidak merujuk ke instans string yang sama.

+ Operator menggabungkan string:

string a = "good " + "morning";

Kode sebelumnya membuat objek string yang berisi "selamat pagi".

String tidak dapat diubah--konten objek string tidak dapat diubah setelah objek dibuat. Misalnya, ketika Anda menulis kode ini, kompilator benar-benar membuat objek string baru untuk menahan urutan karakter baru, dan objek baru tersebut ditetapkan ke b. Memori yang telah dialokasikan untuk b (ketika berisi string "h") kemudian memenuhi syarat untuk pengumpulan sampah.

string b = "h";
b += "ello";

[]Operator dapat digunakan untuk akses baca-saja ke karakter individual string. Nilai indeks yang valid dimulai pada 0 dan harus kurang dari panjang string:

string str = "test";
char x = str[2];  // x = 's';

Dengan cara yang sama, operator [] juga dapat digunakan untuk iterasi atas setiap karakter dalam string:

string str = "test";

for (int i = 0; i < str.Length; i++)
{
  Console.Write(str[i] + " ");
}
// Output: t e s t

Literal string

Harfiah string berjenis string dan dapat ditulis dalam tiga bentuk, mentah, dikutip, dan verbatim.

Harfiah string mentah tersedia mulai dari C# 11. Harfiah string mentah dapat berisi teks arbitrer tanpa memerlukan urutan escape. Harfiah string mentah dapat mencakup spasi kosong dan baris baru, tanda kutip yang disematkan, dan karakter khusus lainnya. Harfiah string mentah diapit dalam minimal tiga tanda kutip ganda ("""):

"""
This is a multi-line
    string literal with the second line indented.
"""

Anda bahkan dapat menyertakan urutan tiga (atau lebih) karakter kutipan ganda. Jika teks Anda memerlukan urutan tanda kutip yang disematkan, Anda memulai dan mengakhiri harfiah string mentah dengan lebih banyak tanda kutip, sesuai kebutuhan:

"""""
This raw string literal has four """", count them: """" four!
embedded quote characters in a sequence. That's why it starts and ends
with five double quotes.

You could extend this example with as many embedded quotes as needed for your text.
"""""

Harfiah string mentah biasanya memiliki urutan kutipan awal dan akhir pada baris terpisah dari teks yang disematkan. Harfiah string mentah multibaris mendukung string yang merupakan string yang dikutip sendiri:

var message = """
"This is a very important message."
""";
Console.WriteLine(message);
// output: "This is a very important message."

Saat tanda kutip awal dan akhir berada di baris terpisah, baris baru yang mengikuti kutipan pembukaan dan sebelum kutipan akhir tidak disertakan dalam konten akhir. Urutan kutipan penutup menentukan kolom paling kiri untuk string harfiah. Anda dapat mengindentasi harfiah string mentah agar sesuai dengan format kode keseluruhan:

var message = """
    "This is a very important message."
    """;
Console.WriteLine(message);
// output: "This is a very important message."
// The leftmost whitespace is not part of the raw string literal

Kolom di sebelah kanan urutan kutipan akhir dipertahankan. Perilaku ini memungkinkan string mentah untuk format data seperti JSON, YAML, atau XML, seperti yang ditunjukkan dalam contoh berikut:

var json= """
    {
        "prop": 0
    }
    """;

Kompilator mengeluarkan kesalahan jika salah satu baris teks meluas ke sebelah kiri urutan kutipan penutup. Urutan kutipan pembuka dan penutup dapat berada di baris yang sama, memberikan harfiah string tidak dimulai atau diakhiri dengan karakter kutipan:

var shortText = """He said "hello!" this morning.""";

Anda dapat menggabungkan harfiah string mentah dengan interpolasi string untuk menyertakan karakter kutipan dan kurung kurawal dalam string output.

Harfiah string yang dikutip diapit dalam tanda kutip ganda ("):

"good morning"  // a string literal

Harfiah string dapat berisi harfiah karakter apa pun. Urutan escape disertakan. Contoh berikut menggunakan urutan escape \\ untuk garis miring terbelakang, \u0066 untuk huruf f, dan \n untuk baris baru.

string a = "\\\u0066\n F";
Console.WriteLine(a);
// Output:
// \f
//  F

Catatan

Kode escape \udddd (tempat dddd adalah angka empat digit) mewakili karakter Unicode U+dddd. Kode escape Unicode delapan digit juga dikenali: \Udddddddd.

Harfiah string verbatim dimulai dengan @ dan juga terlampir dalam tanda kutip ganda. Contohnya:

@"good morning"  // a string literal

Keuntungan dari string verbatim adalah bahwa urutan escape tidak diproses, yang membuatnya mudah ditulis. Misalnya, teks berikut cocok dengan nama file Windows yang sepenuhnya memenuhi syarat:

@"c:\Docs\Source\a.txt"  // rather than "c:\\Docs\\Source\\a.txt"

Untuk menyertakan tanda kutip ganda dalam string @-quoted, gandakan:

@"""Ahoy!"" cried the captain." // "Ahoy!" cried the captain.

Literal string UTF-8

String di .NET disimpan menggunakan pengodean UTF-16. UTF-8 adalah standar untuk protokol Web dan pustaka penting lainnya. Mulai dari C# 11, Anda dapat menambahkan u8 akhiran ke string literal untuk menentukan pengodean UTF-8. UTF-8 literal disimpan sebagai ReadOnlySpan<byte> objek. Jenis alami literal string UTF-8 adalah ReadOnlySpan<byte>. Menggunakan string UTF-8 literal membuat deklarasi yang lebih jelas daripada mendeklarasikan yang setara System.ReadOnlySpan<T>, seperti yang ditunjukkan dalam kode berikut:

ReadOnlySpan<byte> AuthWithTrailingSpace = new byte[] { 0x41, 0x55, 0x54, 0x48, 0x20 };
ReadOnlySpan<byte> AuthStringLiteral = "AUTH "u8;

Untuk menyimpan literal string UTF-8 sebagai array memerlukan penggunaan ReadOnlySpan<T>.ToArray() untuk menyalin byte yang berisi literal ke array yang dapat diubah:

byte[] AuthStringLiteral = "AUTH "u8.ToArray();

Literal string UTF-8 tidak mengkompilasi konstanta waktu; mereka adalah konstanta runtime. Oleh karena itu, mereka tidak dapat digunakan sebagai nilai default untuk parameter opsional. Literal string UTF-8 tidak dapat dikombinasikan dengan interpolasi string. Anda tidak dapat menggunakan $ token dan akhiran u8 pada ekspresi string yang sama.

Jenis delegasi

Deklarasi jenis delegasi mirip dengan tanda tangan metode. Ini memiliki nilai pengembalian dan sejumlah parameter dari jenis apa pun:

public delegate void MessageDelegate(string message);
public delegate int AnotherDelegate(MyType m, long num);

Di .NET, jenis System.Action dan System.Func menyediakan definisi umum untuk banyak delegasi umum. Anda mungkin tidak perlu menentukan jenis delegasi kustom baru. Sebagai gantinya, Anda dapat membuat instansiasi dari jenis generik yang disediakan.

delegate adalah jenis referensi yang dapat digunakan untuk merangkum metode bernama atau anonim. Delegasi mirip dengan penunjuk fungsi di C++; namun delegasi berjenis aman dan terjamin. Untuk aplikasi delegasi, lihat Delegasi dan Delegasi Generik. Delegasi adalah dasar untuk Peristiwa. Delegasi dapat dibuat dengan mengaitkannya baik dengan metode bernama atau anonim.

Delegasi harus dibuat dengan metode atau ekspresi lambda yang memiliki jenis pengembalian dan parameter input yang kompatibel. Untuk informasi selengkapnya tentang tingkat perbedaan yang diizinkan dalam tanda tangan metode, lihat Perbedaan di Delegasi. Untuk digunakan dengan metode anonim, delegasi dan kode yang akan dikaitkan dengannya dideklarasikan bersama-sama.

Mendelegasikan kombinasi atau penghapusan gagal dengan pengecualian runtime ketika jenis delegasi yang terlibat pada waktu proses berbeda karena konversi varian. Contoh berikut menunjukkan situasi yang gagal:

Action<string> stringAction = str => {};
Action<object> objectAction = obj => {};
  
// Valid due to implicit reference conversion of
// objectAction to Action<string>, but may fail
// at run time.
Action<string> combination = stringAction + objectAction;

Anda dapat membuat delegasi dengan jenis runtime yang benar dengan membuat objek delegasi baru. Contoh berikut menunjukkan bagaimana solusi ini dapat diterapkan ke contoh sebelumnya.

Action<string> stringAction = str => {};
Action<object> objectAction = obj => {};
  
// Creates a new delegate instance with a runtime type of Action<string>.
Action<string> wrappedObjectAction = new Action<string>(objectAction);

// The two Action<string> delegate instances can now be combined.
Action<string> combination = stringAction + wrappedObjectAction;

Anda dapat mendeklarasikan penunjuk fungsi, yang menggunakan sintaks serupa. Penunjuk fungsi menggunakan instruksi calli alih-alih membuat instans jenis delegasi dan memanggil metode Invoke virtual.

Jenis dinamis

Jenis dynamic menunjukkan bahwa penggunaan variabel dan referensi ke anggotanya melewati pemeriksaan jenis waktu kompilasi. Sebaliknya, operasi ini diselesaikan pada durasi. Jenis dynamic ini menyederhanakan akses ke API COM seperti OFFICE Automation API, ke API dinamis seperti pustaka IronPython, dan ke HTML Document Object Model (DOM).

Jenis dynamic bertingkah seperti jenis object dalam sebagian besar keadaan. Secara khusus, ekspresi non-null apa pun dapat dikonversi ke jenis dynamic. Jenis dynamic berbeda dari object dalam operasi yang berisi ekspresi jenis dynamic tidak diselesaikan atau jenis yang diperiksa oleh kompilator. Kompilator mengemas informasi bersama tentang operasi, dan informasi tersebut nantinya digunakan untuk mengevaluasi operasi pada durasi. Sebagai bagian dari proses, variabel jenis dynamic dikompilasi menjadi variabel jenis object. Oleh karena itu, jenis dynamic hanya ada pada waktu kompilasi, bukan pada durasi.

Contoh berikut membedakan variabel jenis dynamic ke variabel jenis object. Untuk memverifikasi jenis setiap variabel pada waktu kompilasi, letakkan penunjuk mouse ke atas dyn atau obj dalam pernyataan WriteLine. Salin kode berikut ke editor tempat IntelliSense tersedia. IntelliSense menunjukkan dinamis untuk dyn dan objek untuk obj.

class Program
{
    static void Main(string[] args)
    {
        dynamic dyn = 1;
        object obj = 1;

        // Rest the mouse pointer over dyn and obj to see their
        // types at compile time.
        System.Console.WriteLine(dyn.GetType());
        System.Console.WriteLine(obj.GetType());
    }
}

Pernyataan WriteLine menampilkan jenis run-time dyn dan obj. Pada saat itu, keduanya memiliki jenis yang sama, integer. Output berikut dihasilkan:

System.Int32
System.Int32

Untuk melihat perbedaan antara dyn dan obj pada waktu kompilasi, tambahkan dua baris berikut antara deklarasi dan pernyataan WriteLine dalam contoh sebelumnya.

dyn = dyn + 3;
obj = obj + 3;

Kesalahan kompilator dilaporkan untuk upaya penambahan bilangan bulat dan objek dalam ekspresi obj + 3. Namun, tidak ada kesalahan yang dilaporkan untuk dyn + 3. Ekspresi yang berisi dyn tidak diperiksa pada waktu kompilasi karena jenisnya dyn adalah dynamic.

Contoh berikut menggunakan dynamic dalam beberapa deklarasi. Metode Main ini juga membedakan pemeriksaan jenis waktu kompilasi dengan pemeriksaan jenis run-time.

using System;

namespace DynamicExamples
{
    class Program
    {
        static void Main(string[] args)
        {
            ExampleClass ec = new ExampleClass();
            Console.WriteLine(ec.ExampleMethod(10));
            Console.WriteLine(ec.ExampleMethod("value"));

            // The following line causes a compiler error because ExampleMethod
            // takes only one argument.
            //Console.WriteLine(ec.ExampleMethod(10, 4));

            dynamic dynamic_ec = new ExampleClass();
            Console.WriteLine(dynamic_ec.ExampleMethod(10));

            // Because dynamic_ec is dynamic, the following call to ExampleMethod
            // with two arguments does not produce an error at compile time.
            // However, it does cause a run-time error.
            //Console.WriteLine(dynamic_ec.ExampleMethod(10, 4));
        }
    }

    class ExampleClass
    {
        static dynamic _field;
        dynamic Prop { get; set; }

        public dynamic ExampleMethod(dynamic d)
        {
            dynamic local = "Local variable";
            int two = 2;

            if (d is int)
            {
                return local;
            }
            else
            {
                return two;
            }
        }
    }
}
// Results:
// Local variable
// 2
// Local variable

Spesifikasi bahasa C#

Untuk informasi selengkapnya, lihat bagian berikut dari spesifikasi bahasa C#:

Lihat juga