Jadi saya punya kelas ini:
public class Foo<T> where T : ???
{
private T item;
public bool IsNull()
{
return item == null;
}
}
Sekarang saya mencari batasan tipe yang memungkinkan saya untuk menggunakan semuanya sebagai parameter tipe yang bisa null
. Itu berarti semua jenis referensi, serta semua jenis Nullable
( T?
):
Foo<String> ... = ...
Foo<int?> ... = ...
harus memungkinkan.
Menggunakan class
sebagai batasan tipe hanya memungkinkan saya untuk menggunakan tipe referensi.
Informasi Tambahan:
Saya sedang menulis aplikasi pipa dan filter, dan ingin menggunakan null
referensi sebagai item terakhir yang lolos ke pipa, sehingga setiap filter dapat ditutup dengan baik, melakukan pembersihan, dll ...
IFoo<T>
sebagai jenis kerja dan membuat instance melalui metode pabrik? Itu bisa dibuat untuk bekerja.Jawaban:
Jika Anda ingin melakukan pemeriksaan waktu proses di konstruktor Foo daripada melakukan pemeriksaan waktu kompilasi, Anda dapat memeriksa apakah jenisnya bukan referensi atau jenis nullable, dan memberikan pengecualian jika demikian.
Saya menyadari bahwa hanya melakukan pemeriksaan waktu proses mungkin tidak dapat diterima, tetapi untuk berjaga-jaga:
Kemudian kode berikut dikompilasi, tetapi yang terakhir (
foo3
) melontarkan pengecualian dalam konstruktor:sumber
static bool isValidType
bidang yang Anda setel di konstruktor statis, lalu cukup periksa bendera itu di konstruktor instans dan lempar jika itu jenis yang tidak valid sehingga Anda tidak melakukan semua pekerjaan pemeriksaan setiap kali Anda membuat sebuah contoh. Saya sering menggunakan pola ini.Saya tidak tahu bagaimana menerapkan setara dengan OR di obat generik. Namun saya dapat mengusulkan untuk menggunakan kata kunci default untuk membuat null untuk tipe nullable dan nilai 0 untuk struktur:
Anda juga bisa mengimplementasikan versi Nullable Anda:
Contoh:
sumber
Saya mengalami masalah ini untuk kasus sederhana yang menginginkan metode statis generik yang dapat mengambil apa pun "nullable" (baik jenis referensi atau Nullables), yang membawa saya ke pertanyaan ini tanpa solusi yang memuaskan. Jadi saya datang dengan solusi saya sendiri yang relatif lebih mudah untuk dipecahkan daripada pertanyaan yang dinyatakan OP dengan hanya memiliki dua metode kelebihan beban, satu yang mengambil
T
dan memiliki kendalawhere T : class
dan yang lain yang mengambilT?
dan memilikiwhere T : struct
.Saya kemudian menyadari, solusi itu juga dapat diterapkan pada masalah ini untuk membuat solusi yang dapat diperiksa pada waktu kompilasi dengan membuat konstruktor pribadi (atau dilindungi) dan menggunakan metode pabrik statis:
Sekarang kita bisa menggunakannya seperti ini:
Jika Anda menginginkan konstruktor tanpa parameter, Anda tidak akan mendapatkan kelebihan beban, tetapi Anda masih dapat melakukan sesuatu seperti ini:
Dan gunakan seperti ini:
Ada beberapa kelemahan dari solusi ini, salah satunya adalah Anda mungkin lebih suka menggunakan 'baru' untuk membuat objek. Lain adalah bahwa Anda tidak akan dapat menggunakan
Foo<T>
sebagai jenis argumen generik untuk jenis kendala sesuatu seperti:where TFoo: new()
. Terakhir adalah sedikit kode tambahan yang Anda butuhkan di sini yang akan meningkat terutama jika Anda membutuhkan banyak konstruktor yang kelebihan beban.sumber
Seperti yang disebutkan, Anda tidak dapat memiliki pemeriksaan waktu kompilasi untuk itu. Batasan umum di .NET sangat kurang, dan tidak mendukung sebagian besar skenario.
Namun saya menganggap ini sebagai solusi yang lebih baik untuk pemeriksaan run-time. Ini dapat dioptimalkan pada waktu kompilasi JIT, karena keduanya adalah konstanta.
sumber
Batasan tipe seperti itu tidak mungkin. Menurut dokumentasi batasan tipe, tidak ada batasan yang menangkap tipe referensi dan nullable. Karena batasan hanya dapat digabungkan, tidak ada cara untuk membuat batasan seperti itu dengan kombinasi.
Namun, Anda dapat, untuk kebutuhan Anda, kembali ke parameter tipe yang tidak dibatasi, karena Anda selalu dapat memeriksa == null. Jika tipe adalah tipe nilai, pemeriksaan hanya akan selalu bernilai salah. Kemudian Anda mungkin akan mendapatkan peringatan R # "Kemungkinan perbandingan tipe nilai dengan null", yang tidak penting, selama semantiknya tepat untuk Anda.
Alternatif bisa digunakan
alih-alih pemeriksaan null, karena default (T) di mana T: class selalu null. Ini, bagaimanapun, berarti bahwa Anda tidak dapat membedakan cuaca, nilai yang tidak dapat dinihilkan tidak pernah ditetapkan secara eksplisit atau hanya disetel ke nilai defaultnya.
sumber
saya menggunakan
sumber
sumber