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.
Petunjuk / Saran
Baru mengembangkan perangkat lunak? Mulai dengan tutorial Memulai terlebih dahulu. Anda akan menemukan struct ketika Anda memerlukan tipe nilai ringan dalam kode Anda.
Berpengalaman dalam bahasa lain? Struktur C# adalah tipe nilai yang mirip dengan struktur di C++ atau Swift, tetapi dapat berada di heap terkelola ketika di-"box" dan mendukung antarmuka, konstruktor, serta metode. Telusuri bagian readonly structs untuk pola yang khusus untuk C#. Untuk struktur rekaman, lihat Rekaman.
Struktur adalah tipe nilai yang menyimpan datanya langsung dalam instans, bukan melalui referensi ke objek pada heap. Saat Anda menetapkan struct ke variabel baru, runtime menyalin seluruh instans. Perubahan pada satu variabel tidak memengaruhi variabel lainnya karena setiap variabel mewakili instans yang berbeda. Gunakan struktur untuk jenis kecil dan ringan yang peran utamanya menyimpan data daripada perilaku pemodelan. Contohnya termasuk koordinat, warna, pengukuran, atau pengaturan konfigurasi.
Kapan Menggunakan Struct
Gunakan struct ketika tipe Anda:
- Mewakili nilai tunggal atau sekelompok kecil nilai terkait (kira-kira 16 byte atau kurang).
- Memiliki semantik nilai—dua instans dengan data yang sama harus dianggap setara.
- Terutama merupakan kontainer data daripada model perilaku.
- Tidak memerlukan pewarisan dari jenis dasar (struktur tidak dapat mewarisi dari struktur atau kelas lain, tetapi dapat menerapkan antarmuka).
Untuk perbandingan yang lebih luas yang mencakup kelas, rekaman, tuple, dan antarmuka, lihat Memilih jenis jenis mana.
Mendeklarasikan struktur
Tentukan struktur dengan struct kata kunci. Struktur dapat berisi bidang, properti, metode, dan konstruktor, sama seperti kelas:
struct Point
{
public double X { get; set; }
public double Y { get; set; }
public readonly double DistanceTo(Point other)
{
var dx = X - other.X;
var dy = Y - other.Y;
return Math.Sqrt(dx * dx + dy * dy);
}
public override string ToString() => $"({X}, {Y})";
}
Struktur Point menyimpan dua double nilai dan menyediakan metode untuk menghitung jarak antara dua titik. Metode DistanceTo ditandai readonly karena tidak mengubah status struct. Pola itu tercakup dalam anggota readonly.
Semantik nilai
Struktur adalah jenis nilai. Penugasan menyalin data, sehingga setiap variabel menyimpan salinan independennya sendiri:
var p1 = new Point { X = 3, Y = 4 };
var p2 = p1; // copies the data
p2.X = 10;
Console.WriteLine(p1); // (3, 4) — p1 is unchanged
Console.WriteLine(p2); // (10, 4) — only p2 was modified
Karena struktur adalah kontainer data, penugasan menyalin setiap anggota data ke dalam instans independen baru. Setiap salinan berbeda. Mengubah salah satunya tidak memengaruhi yang lain. Perilaku ini berbeda dari kelas, di mana penugasan hanya menyalin referensi dan kedua variabel berbagi objek yang sama. Untuk informasi selengkapnya tentang perbedaannya, lihat Jenis nilai dan jenis referensi.
Konstruktor untuk struct
Anda dapat menentukan konstruktor dalam struktur dengan cara yang sama seperti yang Anda lakukan di kelas. Struktur dapat memiliki konstruktor tanpa parameter yang mengatur nilai default kustom. Istilah "konstruktor tanpa parameter" membedakan instans yang dibuat dengan new (yang menjalankan logika konstruktor Anda) dari instans default yang dibuat dengan default ekspresi (yang menginisialisasi nol semua bidang):
struct ConnectionSettings
{
public string Host { get; set; }
public int Port { get; set; }
public int MaxRetries { get; set; }
public ConnectionSettings()
{
Host = "localhost";
Port = 8080;
MaxRetries = 3;
}
}
Konstruktor tanpa parameter berjalan saat Anda menggunakan new tanpa argumen. Ekspresi default melewati konstruktor dan mengatur semua bidang ke nilai defaultnya (0, null, false). Perhatikan perbedaannya:
var custom = new ConnectionSettings();
Console.WriteLine($"{custom.Host}:{custom.Port} (retries: {custom.MaxRetries})");
// localhost:8080 (retries: 3)
var defaults = default(ConnectionSettings);
Console.WriteLine($"{defaults.Host ?? "(null)"}:{defaults.Port} (retries: {defaults.MaxRetries})");
// (null):0 (retries: 0)
Pengkompilasi secara otomatis menginisialisasi bidang apa pun yang tidak Anda tetapkan secara eksplisit dalam konstruktor. Anda hanya dapat menginisialisasi bidang yang memerlukan nilai non-default:
struct GameTile
{
public int Row { get; set; }
public int Column { get; set; }
public bool IsBlocked { get; set; }
public GameTile(int row, int column)
{
Row = row;
Column = column;
// IsBlocked is automatically initialized to false
}
}
Contoh berikut menampilkan nilai default untuk IsBlocked:
var tile = new GameTile(2, 5);
Console.WriteLine($"Tile ({tile.Row}, {tile.Column}), blocked: {tile.IsBlocked}");
// Tile (2, 5), blocked: False
Properti IsBlocked tidak ditetapkan dalam konstruktor, sehingga pengkompilasi mengaturnya ke false (default untuk bool). Fitur ini mengurangi boilerplate dalam konstruktor yang hanya perlu mengatur beberapa kolom.
Struktur readonly dan anggota readonly
Sebuah readonly struct menjamin bahwa tidak ada anggota instans yang dapat memodifikasi status struct. Kompilator memberlakukan jaminan ini dengan mensyaratkan semua field dan properti yang diimplementasikan secara otomatis menjadi hanya-baca.
readonly struct Temperature
{
public double Celsius { get; }
public Temperature(double celsius) => Celsius = celsius;
public double Fahrenheit => Celsius * 9.0 / 5.0 + 32.0;
public override string ToString() => $"{Celsius:F1}°C ({Fahrenheit:F1}°F)";
}
Contoh berikut membuat instans Temperature dan membaca propertinya:
var temp = new Temperature(100);
Console.WriteLine(temp); // 100.0°C (212.0°F)
// temp.Celsius = 50; // Error: property is read-only
Ketika Anda tidak memerlukan seluruh struktur agar tidak dapat diubah, tandai anggota individu sebagai readonly gantinya. Anggota readonly tidak dapat memodifikasi status struktur, dan pengkompilasi memverifikasi jaminan tersebut:
struct Velocity
{
public double X
{
readonly get;
set;
}
public double Y
{
readonly get;
set;
}
public readonly double Speed => Math.Sqrt(X * X + Y * Y);
public readonly override string ToString() => $"({X}, {Y}) speed={Speed:F2}";
}
Contoh berikut menunjukkan bahwa anggota akan mengembalikan nilai yang diperbarui saat properti yang dapat diubah diperbarui:
var v = new Velocity { X = 3, Y = 4 };
Console.WriteLine(v.Speed); // 5
Console.WriteLine(v); // (3, 4) speed=5.00
v.X = 6;
Console.WriteLine(v.Speed); // 7.211...
Menandai anggota readonly membantu pengkompilasi mengoptimalkan salinan defensif. Ketika Anda meneruskan readonly struct ke metode yang menerima in parameter, pengkompilasi tahu tidak ada salinan yang diperlukan.