Saya memiliki kelas dengan dua readonly int
bidang. Mereka terpapar sebagai properti:
public class Thing
{
private readonly int _foo, _bar;
/// <summary> I AM IMMUTABLE. </summary>
public Thing(int foo, int bar)
{
_foo = foo;
_bar = bar;
}
public int Foo { get { return _foo; } set { } }
public int Bar { get { return _bar; } set { } }
}
Namun, itu berarti bahwa kode berikut ini benar-benar legal:
Thing iThoughtThisWasMutable = new Thing(1, 42);
iThoughtThisWasMutable.Foo = 99; // <-- Poor, mistaken developer.
// He surely has bugs now. :-(
Bug yang berasal dari asumsi itu akan berhasil pasti akan membahayakan. Tentu, pengembang yang salah seharusnya membaca dokumen. Tapi itu tidak mengubah fakta bahwa tidak ada kesalahan kompilasi atau run-time yang memperingatkannya tentang masalah tersebut.
Bagaimana seharusnya Thing
kelas diubah sehingga para pengembang cenderung membuat kesalahan di atas?
Melempar pengecualian? Gunakan metode pengambil alih-alih properti?
c#
object-oriented
immutability
properties
kdbanman
sumber
sumber
Interfaces
. Saya tidak yakin itu yang saya lakukan.Jawaban:
Mengapa membuat kode itu legal?
Keluarkan
set { }
jika tidak melakukan apa-apa.Ini adalah cara Anda mendefinisikan properti publik hanya baca:
sumber
public int Foo { get; }
(properti otomatis dengan pengambil)public int Foo { get; private set; }
.Dengan C # 5 dan sebelumnya, kami dihadapkan dengan dua opsi untuk bidang yang tidak berubah yang diekspos melalui pengambil:
readonly
untuk menghancurkan ketidakberdayaan. Ini membuat banyak kode boiler-plate.Dengan C # 6 (tersedia di VS2015, yang dirilis kemarin), kami sekarang mendapatkan yang terbaik dari kedua dunia: properti otomatis hanya-baca. Ini memungkinkan kami untuk menyederhanakan kelas OP menjadi:
Garis
Foo = foo
danBar = bar
hanya valid dalam konstruktor (yang mencapai persyaratan read-only yang kuat) dan bidang dukungan tersirat, daripada harus didefinisikan secara eksplisit (yang mencapai kode lebih sederhana).sumber
Anda bisa saja menyingkirkan setter. Mereka tidak melakukan apa-apa, mereka akan membingungkan pengguna dan mereka akan menyebabkan bug. Namun, Anda bisa menjadikannya pribadi dan dengan demikian menyingkirkan variabel pendukung, menyederhanakan kode Anda:
sumber
public int Foo { get; private set; }
" Kelas itu tidak lagi abadi karena bisa berubah sendiri. Terimakasih Meskipun!readonly
kata kunci hanya poka-yoke, yaitu itu penjaga terhadap kelas melanggar immutablity di masa depan; itu tidak diperlukan untuk mencapai keabadian.Dua solusi.
Sederhana:
Jangan sertakan setter seperti yang dicatat oleh David untuk objek yang hanya bisa dibaca yang tidak berubah.
Kalau tidak:
Izinkan setter untuk mengembalikan objek yang tidak dapat diubah baru, verbose dibandingkan dengan yang sebelumnya tetapi memberikan status dari waktu ke waktu untuk setiap objek yang diinisialisasi. Desain ini adalah alat yang sangat berguna untuk keselamatan dan kekekalan Thread yang mencakup semua bahasa OOP yang penting.
Kodesemu
pabrik statis publik
sumber