public sealed class Singleton
{
Singleton() {}
public static Singleton Instance
{
get
{
return Nested.instance;
}
}
class Nested
{
// Explicit static constructor to tell C# compiler
// not to mark type as beforefieldinit
static Nested() {}
internal static readonly Singleton instance = new Singleton();
}
}
Saya ingin menerapkan pola Singleton Jon Skeet dalam aplikasi saya saat ini di C #.
Saya memiliki dua keraguan pada kode tersebut
Bagaimana mungkin mengakses kelas luar di dalam kelas bersarang? maksudku
internal static readonly Singleton instance = new Singleton();
Apakah sesuatu yang disebut penutupan?
Saya tidak dapat memahami komentar ini
// Explicit static constructor to tell C# compiler // not to mark type as beforefieldinit
apa komentar ini menyarankan kita?
c#
.net
design-patterns
architecture
singleton
amutha
sumber
sumber
Jawaban:
Tidak, ini tidak ada hubungannya dengan penutupan. Kelas bersarang memiliki akses ke anggota pribadi kelas luarnya, termasuk konstruktor pribadi di sini.
Baca artikel saya di beforefieldinit . Anda mungkin atau mungkin tidak ingin konstruktor statis no-op - itu tergantung pada jaminan kemalasan yang Anda butuhkan. Anda harus menyadari bahwa .NET 4 mengubah semantik inisialisasi tipe aktual (masih dalam spesifikasi, tetapi lebih malas dari sebelumnya).
Apakah Anda benar - benar membutuhkan pola ini? Anda yakin tidak bisa lolos dengan:
sumber
Lazy<T>
sehingga Anda tidak perlu mendeklarasikan konstruktor statis untukBeforeFieldInit
efek samping ajaib ?FieldBeforeInit
berasalMahaBharata
dariMicrosoft
Mengenai pertanyaan (1): Jawaban dari Jon benar, karena ia secara implisit menandai kelas 'Bersarang' pribadi dengan tidak menjadikannya publik atau internal :-). Anda sebaiknya melakukannya secara eksplisit dengan menambahkan 'pribadi':
Mengenai pertanyaan (2): pada dasarnya apa posting tentang beforeinitfield dan tipe inisialisasi memberitahu Anda adalah bahwa jika Anda tidak memiliki konstruktor statis, runtime dapat menginisialisasi kapan saja (tetapi sebelum Anda menggunakannya). Jika Anda memiliki konstruktor statis, kode Anda di konstruktor statis mungkin menginisialisasi bidang, yang berarti bahwa runtime hanya diperbolehkan untuk menginisialisasi bidang ketika Anda meminta jenis.
Jadi jika Anda tidak ingin runtime menginisialisasi bidang 'secara proaktif' sebelum Anda menggunakannya, tambahkan konstruktor statis.
Either way, jika Anda menerapkan lajang Anda juga ingin inisialisasi sebagai malas mungkin dan tidak ketika runtime berpikir itu harus menginisialisasi variabel Anda - atau Anda mungkin tidak peduli. Dari pertanyaan Anda, saya kira Anda menginginkannya selambat-lambatnya.
Itu membawa bertemu ke posting Jon tentang singleton , yang merupakan topik mendasar dari pertanyaan ini. Oh dan keraguannya :-)
Saya ingin menunjukkan bahwa singleton # 3-nya, yang dia tandai 'salah', sebenarnya benar (karena kunci secara otomatis menyiratkan penghalang memori saat keluar ). Itu juga harus lebih cepat daripada singleton # 2 ketika Anda menggunakan instance lebih dari sekali (yang kurang lebih merupakan poin dari singleton :-)). Jadi, jika Anda benar-benar membutuhkan implementasi tunggal yang malas, saya mungkin akan menggunakan yang pertama - untuk alasan sederhana bahwa (1) sangat jelas bagi semua orang yang membaca kode Anda apa yang sedang terjadi dan (2) Anda tahu apa yang akan terjadi dengan pengecualian.
Jika Anda bertanya-tanya: Saya tidak akan pernah menggunakan singleton # 6 karena dapat dengan mudah menyebabkan kebuntuan dan perilaku tak terduga dengan pengecualian. Untuk detailnya, lihat: mode penguncian lazy , khususnya ExecutionAndPublication.
sumber
Regarding question (1): The answer from Jon is correct ...
Jon Skeet selalu benar ....