Ini menyebabkan pengecualian waktu kompilasi:
public sealed class ValidatesAttribute<T> : Attribute
{
}
[Validates<string>]
public static class StringValidation
{
}
Saya menyadari C # tidak mendukung atribut generik. Namun, setelah banyak Googling, saya tidak dapat menemukan alasannya.
Adakah yang tahu mengapa tipe generik tidak dapat diturunkan Attribute
? Ada teori?
c#
generics
.net-attributes
Bryan Watts
sumber
sumber
abstract class Base<T>: Attribute {}
yang dapat digunakan untuk membuat non- kelas turunan generik seperti ini:class Concrete: Base<MyType> {}
[DependsOnProperty<Foo>(f => f.Bar)]
atau[ForeignKey<Foo>(f => f.IdBar)]
...Jawaban:
Yah, saya tidak bisa menjawab mengapa itu tidak tersedia, tetapi saya dapat mengkonfirmasi bahwa ini bukan masalah CLI. Spesifikasi CLI tidak menyebutkannya (sejauh yang saya bisa lihat) dan jika Anda menggunakan IL secara langsung, Anda dapat membuat atribut generik. Bagian dari spesifikasi C # 3 yang melarangnya - bagian 10.1.4 "Spesifikasi dasar kelas" tidak memberikan justifikasi apa pun.
Spesifikasi ECMA C # 2 yang dianotasi juga tidak memberikan informasi bermanfaat, meskipun itu memberikan contoh tentang apa yang tidak diperbolehkan.
Salinan spec C # 3 saya yang beranotasi akan tiba besok ... Saya akan melihat apakah itu memberikan informasi lebih lanjut. Bagaimanapun, ini jelas merupakan keputusan bahasa daripada yang runtime.
EDIT: Jawaban dari Eric Lippert (diparafrasekan): tidak ada alasan khusus, kecuali untuk menghindari kompleksitas dalam bahasa dan kompiler untuk kasus penggunaan yang tidak menambah banyak nilai.
sumber
Atribut mendekorasi kelas pada waktu kompilasi, tetapi kelas generik tidak menerima informasi tipe terakhirnya sampai runtime. Karena atribut dapat mempengaruhi kompilasi, itu harus "selesai" pada waktu kompilasi.
Lihat artikel MSDN ini untuk informasi lebih lanjut.
sumber
Saya tidak tahu mengapa itu tidak diizinkan, tetapi ini adalah salah satu solusi yang mungkin
sumber
Ini bukan benar-benar generik dan Anda masih harus menulis kelas atribut spesifik per jenis, tetapi Anda mungkin dapat menggunakan antarmuka basis generik untuk mengkodekan sedikit defensif, menulis kode lebih sedikit daripada yang diperlukan, mendapatkan manfaat polimorfisme dll.
sumber
Ini pertanyaan yang sangat bagus. Dalam pengalaman saya dengan atribut, saya pikir kendala di tempat karena ketika merefleksikan atribut itu akan menciptakan suatu kondisi di mana Anda harus memeriksa semua jenis kemungkinan permutasi:
typeof(Validates<string>)
,typeof(Validates<SomeCustomType>)
, dll ...Menurut pendapat saya, jika validasi khusus diperlukan tergantung pada jenisnya, atribut mungkin bukan pendekatan terbaik.
Mungkin kelas validasi yang menggunakan a
SomeCustomValidationDelegate
atau aISomeCustomValidator
sebagai parameter akan menjadi pendekatan yang lebih baik.sumber
Ini bukan fitur bahasa C # saat ini, namun ada banyak diskusi tentang repo bahasa C # resmi .
Dari beberapa catatan rapat :
sumber
Solusi saya adalah seperti ini:
sumber