Perbedaan C # antara gaya pengambil yang berbeda

154

Kadang-kadang saya melihat singkatan di properti untuk rajin dan giat. Misal kedua jenis itu:

public int Number { get; } = 0

public int Number => 0;

Dapatkah seseorang tolong beri tahu saya jika ada perbedaan antara keduanya. Bagaimana mereka berperilaku? Apakah keduanya hanya baca-saja?

WoIIe
sumber

Jawaban:

266

Ya, keduanya hanya baca, tetapi ada perbedaan. Di yang pertama, ada bidang dukungan yang diinisialisasi ke 0 sebelum konstruktor dijalankan. Anda dapat mengubah nilai hanya di konstruktor , seperti bidang baca-saja biasa. The getter itu sendiri hanya mengembalikan nilai field.

Pada yang kedua, pengambil hanya mengembalikan 0 setiap kali, tanpa bidang yang terlibat.

Jadi untuk menghindari penggunaan properti yang diimplementasikan secara otomatis atau anggota yang bertubuh ekspresi sama sekali, kami memiliki:

Versi pertama

private readonly int _number = 0;
public int Number { get { return _number; } }

Versi kedua

public int Number { get { return 0; } }

Contoh perbedaan yang lebih jelas mungkin terlihat seperti ini:

public DateTime CreationTime { get; } = DateTime.UtcNow;
public DateTime CurrentTime => DateTime.UtcNow;

Jika Anda membuat objek tunggal, CreationTimepropertinya akan selalu memberikan hasil yang sama - karena disimpan dalam bidang hanya baca, diinisialisasi pada konstruksi objek. Namun, setiap kali Anda mengakses CurrentTimeproperti, itu akan menyebabkan DateTime.UtcNowdievaluasi, sehingga Anda akan mendapatkan hasil yang berpotensi berbeda.

Jon Skeet
sumber
23
Perhatikan bahwa versi kedua tidak selalu mengembalikan nilai yang sama. Salah satu contoh yang baik adalah jika Anda kembali random.NextInt(). Versi pertama akan mengevaluasi itu sekali dan selalu memiliki nilai yang sama. Yang kedua akan mengembalikan nilai baru setiap kali.
248

Satu perbedaan adalah ketika hal 0itu dievaluasi: pada saat pembuatan objek atau ketika properti digunakan.

Anda dapat melihat ini lebih baik dengan properti DateTime:

class SomeTestClass
{
    public DateTime Start { get; } = DateTime.Now;

    public DateTime Now => DateTime.Now;
}

The Startproperti terus kembali waktu yang sama (dari ketika misalnya diciptakan), sedangkan Nowperubahan untuk mencerminkan waktu saat ini.

Penjelasan :

Versi pertama ("Mulai") memasok nilai awal yang bahkan mungkin ditimpa oleh konstruktor. Jadi ini dievaluasi sekali saja.
Versi kedua ("Sekarang") memberikan ekspresi yang akan menjadi "pengambil" properti ini. Jadi ini dievaluasi setiap kali properti dibaca. Bahkan tidak ada bidang dukungan yang dapat ditimpa oleh konstruktor.

Hans Ke st ing
sumber
26
Ini adalah perbedaan yang paling penting menurut saya.
Matius
14
Jawaban yang diterima paling tepat mendefinisikan perbedaan dalam kode contoh, tetapi ini menjelaskan perbedaan yang lebih berguna dalam dua struktur.
Kamil Drakari
3
Wow, Anda mendapat lebih banyak suara daripada Jon Skeet yang terkenal itu sendiri.
machine_1
21

Ini adalah fitur bahasa C # 6.

Contoh pertama

public int Number { get; } = 0

Contoh pertama adalah properti otomatis pengambil-saja . Bidang dukungan properti pengambil otomatis saja secara implisit dinyatakan sebagai hanya dapat dibaca.

Contoh kedua

public int Number => 0;

Dan contoh kedua adalah ekspresi tubuh pada anggota fungsi seperti properti . Perhatikan bahwa tidak ada getkata kunci: Ini tersirat oleh penggunaan sintaksis ekspresi tubuh.

Keduanya hanya bisa dibaca.

Yah
sumber
5
... tetapi seperti yang dijelaskan Jon Skeet, Anda dapat mengubah nilai yang dikembalikan pertama.
Martin Bonner mendukung Monica
2
@ MartinBonner ... tetapi hanya di konstruktor.
Dennis Kuypers
5
atau, seperti biasa, melalui refleksi (nitpicking kecil)
Marco Mp