Di C #,
Apakah ada cara untuk mengubah properti otomatis menjadi properti otomatis yang lambat dimuat dengan nilai default yang ditentukan?
Pada dasarnya, saya mencoba mengubah ini ...
private string _SomeVariable
public string SomeVariable
{
get
{
if(_SomeVariable == null)
{
_SomeVariable = SomeClass.IOnlyWantToCallYouOnce();
}
return _SomeVariable;
}
}
menjadi sesuatu yang berbeda, di mana saya dapat menentukan default dan menangani sisanya secara otomatis ...
[SetUsing(SomeClass.IOnlyWantToCallYouOnce())]
public string SomeVariable {get; private set;}
c#
automatic-properties
ctorx.dll
sumber
sumber
Jawaban:
Tidak, tidak ada. Properti yang diimplementasikan secara otomatis hanya berfungsi untuk mengimplementasikan properti yang paling dasar: backing field dengan pengambil dan penyetel. Itu tidak mendukung jenis penyesuaian ini.
Namun Anda dapat menggunakan
Lazy<T>
tipe 4.0 untuk membuat pola iniKode ini akan dengan malas menghitung nilai
_someVariable
pertama kaliValue
ekspresi dipanggil. Ini hanya akan dihitung sekali dan akan menyimpan nilai untuk penggunaanValue
properti di masa mendatangsumber
SomeClass.IOnlyWantToCallYouOnce
dalam contoh Anda harus statis untuk digunakan dengan penginisialisasi bidang.Mungkin yang paling ringkas yang bisa Anda dapatkan adalah menggunakan operator penggabungan-nol:
sumber
IOnlyWantToCallYouOnce
pengembaliannull
itu akan memanggilnya lebih dari sekali._SomeVariable ?? ( _SomeVariable = SomeClass.IOnlyWantToCallYouOnce() );
- perhatikan penambahan tanda kurung di sekitar pengaturan_SomeVariable
jika nol.Lazy<>
, tetapi untuk tujuan kami ini bekerja lebih baik. Dengan C # terbaru itu juga dapat ditulis lebih ringkas=> _SomeVariable ?? (_SomeVariable = SomeClass.IOnlyWantToCallYouOnce());
Apa yang mungkin tidak diperhatikan beberapa orang dari tampilan pertama adalah bahwa operator mengevaluasi operan kanan dan mengembalikan hasilnya .Ada fitur baru di C # 6 yang disebut Expression Bodied Auto-Properties , yang memungkinkan Anda menulisnya sedikit lebih bersih:
Sekarang dapat ditulis sebagai:
sumber
IOnlyWantToCallYouOnce
akan dipanggil selama konstruksi setiap kali kelas dibuat.SomeVariable
malas dimuat.Tidak seperti itu, parameter untuk atribut harus bernilai konstan, Anda tidak dapat memanggil kode (Bahkan kode statis).
Namun Anda mungkin dapat menerapkan sesuatu dengan PostSharp's Aspects.
Periksa mereka:
PostSharp
sumber
Inilah implementasi saya untuk memecahkan masalah Anda. Pada dasarnya idenya adalah properti yang akan ditetapkan oleh fungsi pada akses pertama dan akses selanjutnya akan menghasilkan nilai pengembalian yang sama seperti yang pertama.
Kemudian gunakan:
Tentu saja ada overhead untuk melewatkan function pointer, tetapi itu melakukan pekerjaan untuk saya dan saya tidak melihat terlalu banyak overhead dibandingkan dengan menjalankan metode berulang kali.
sumber
Saya penggemar berat ide ini, dan ingin menawarkan cuplikan C # berikut yang saya sebut proplazy.snippet. (Anda dapat mengimpor ini atau menempelkannya ke folder standar yang dapat Anda peroleh dari Snippet Manager)
Berikut contoh keluarannya:
Berikut konten file cuplikan: (simpan sebagai proplazy.snippet)
sumber
Saya tidak berpikir ini mungkin dengan C # murni. Tetapi Anda dapat melakukannya dengan menggunakan penulis ulang IL seperti PostSharp . Misalnya memungkinkan Anda untuk menambahkan penangan fungsi sebelum dan sesudah bergantung pada atribut.
sumber
Saya melakukannya seperti ini:
dan nanti Anda bisa menggunakannya seperti
sumber
public ISet<String> RegularProperty {get;set} public string CalculatedProperty => this.LazyValue(() => { return string.Join(",", RegularProperty.ToArray()); });
Operator ?? = tersedia menggunakan C # 8.0 dan yang lebih baru, jadi Anda sekarang dapat melakukannya dengan lebih ringkas:
sumber
https://github.com/bcuff/AutoLazy menggunakan Fody untuk memberi Anda sesuatu seperti ini
sumber
dan saya menelepon seperti di bawah
sumber
Jika Anda menggunakan konstruktor selama inisialisasi lambat, ekstensi berikut mungkin berguna juga
Pemakaian
sumber
LazyInitializer.EnsureInitialized()
? Karena dari apa yang saya tahu, selain fungsionalitas di atas,LazyInitializer
menyediakan fungsi penanganan kesalahan serta sinkronisasi. Kode sumber LazyInitializer .