Saat ini saya sedang menulis beberapa kode untuk UnconstrainedMelody yang memiliki metode umum untuk dilakukan dengan enum.
Sekarang, saya memiliki kelas statis dengan banyak metode yang hanya dimaksudkan untuk digunakan dengan enum "flags". Saya tidak dapat menambahkan ini sebagai pembatas ... jadi mungkin saja mereka akan dipanggil dengan jenis enum lain juga. Dalam hal ini, saya ingin memberikan pengecualian, tetapi saya tidak yakin mana yang harus dibuang.
Hanya untuk membuat ini menjadi konkret, jika saya memiliki sesuatu seperti ini:
// Returns a value with all bits set by any values
public static T GetBitMask<T>() where T : struct, IEnumConstraint
{
if (!IsFlags<T>()) // This method doesn't throw
{
throw new ???
}
// Normal work here
}
Apa pengecualian terbaik untuk dilempar? ArgumentException
terdengar logis, tapi ini adalah tipe argumen daripada argumen normal, yang dapat dengan mudah membingungkan banyak hal. Haruskah saya memperkenalkan TypeArgumentException
kelas saya sendiri ? Gunakan InvalidOperationException
? NotSupportedException
? Ada yang lain?
Saya lebih suka tidak membuat pengecualian saya sendiri untuk ini kecuali hal ini jelas merupakan hal yang benar untuk dilakukan.
Jawaban:
NotSupportedException
kedengarannya cocok, tetapi dokumentasinya dengan jelas menyatakan bahwa itu harus digunakan untuk tujuan yang berbeda. Dari catatan kelas MSDN:Tentu saja, ada cara yang
NotSupportedException
jelas-jelas cukup bagus, terutama mengingat arti yang masuk akal. Karena itu, saya tidak yakin apakah itu tepat.Mengingat tujuan Melodi Tanpa Batas ...
... sepertinya yang baru
Exception
mungkin beres meskipun beban pembuktiannya tinggi yang harus kita penuhi sebelum membuat kebiasaanExceptions
. Sesuatu sepertiInvalidTypeParameterException
mungkin berguna di seluruh perpustakaan (atau mungkin tidak - ini pasti kasus tepi, kan?).Apakah klien harus dapat membedakan ini dari Pengecualian BCL? Kapan klien tidak sengaja memanggil ini menggunakan vanilla
enum
? Bagaimana Anda akan menjawab pertanyaan yang diajukan oleh jawaban yang diterima untuk Faktor apa yang harus dipertimbangkan saat menulis kelas pengecualian khusus?sumber
InvalidOperationException
menjijikkan, karena "Foo meminta Bilah Pengumpul untuk menambahkan sesuatu yang sudah ada, jadi Bilah melempar IOE" dan "Foo meminta Bilah Pengumpul untuk menambahkan sesuatu, jadi Bar memanggil Boz yang melempar IOE meskipun Bar tidak mengharapkannya" keduanya akan menampilkan tipe pengecualian yang sama; kode yang mengharapkan untuk menangkap yang pertama tidak akan mengharapkan yang terakhir. Yang telah dikatakan ...Foo<T>
sebagai "tipe umum", danFoo<Bar>
menjadi "tipe khusus" dalam konteks itu, meskipun tidak ada hubungan "warisan" di antara mereka.Saya akan menghindari NotSupportedException. Pengecualian ini digunakan dalam kerangka kerja di mana metode tidak diimplementasikan dan terdapat properti yang menunjukkan bahwa jenis operasi ini tidak didukung. Tidak muat di sini
Menurut saya, InvalidOperationException adalah pengecualian paling tepat yang dapat Anda berikan di sini.
sumber
T
adalahenum
dihiasi denganFlags
, itu akan berlaku untuk membuang NSE.StupidClrException
membuat nama yang menyenangkan;)Pemrograman generik tidak boleh melempar pada waktu proses untuk parameter tipe yang tidak valid. Seharusnya tidak dikompilasi, Anda harus memiliki penegakan waktu kompilasi. Saya tidak tahu
IsFlag<T>()
isinya, tapi mungkin Anda bisa mengubahnya menjadi penegakan waktu kompilasi, seperti mencoba membuat tipe yang hanya mungkin dibuat dengan 'flags'. Mungkintraits
kelas bisa membantu.Memperbarui
Jika Anda harus melempar, saya akan memilih InvalidOperationException. Alasannya adalah bahwa tipe generik memiliki parameter dan kesalahan yang terkait dengan parameter (metode) yang berpusat di sekitar hierarki ArgumentException. Namun, rekomendasi pada ArgumentException menyatakan itu
Setidaknya ada satu lompatan keyakinan di sana, bahwa rekomendasi parameter metode juga akan diterapkan ke parameter umum , tetapi tidak ada yang lebih baik dalam hierachy imho SystemException.
sumber
IsFlag<T>
menentukan apakah enum telah[FlagsAttribute]
diterapkan padanya, dan CLR tidak memiliki batasan berdasarkan atribut. Itu akan terjadi di dunia yang sempurna - atau akan ada cara lain untuk membatasinya - tetapi dalam kasus ini itu tidak berhasil :(Saya akan menggunakan NotSupportedException karena itulah yang Anda katakan. Enum selain yang spesifik tidak didukung . Ini tentu saja akan dinyatakan dengan lebih jelas dalam pesan pengecualian.
sumber
Saya akan pergi dengan
NotSupportedException
. MeskipunArgumentException
terlihat bagus, itu benar-benar diharapkan ketika argumen yang diteruskan ke suatu metode tidak dapat diterima. Argumen tipe adalah karakteristik yang menentukan untuk metode sebenarnya yang ingin Anda panggil, bukan "argumen" yang sebenarnya.InvalidOperationException
harus dibuang ketika operasi yang Anda lakukan bisa valid dalam beberapa kasus, tetapi untuk situasi tertentu, itu tidak dapat diterima.NotSupportedException
dilempar saat operasi tidak didukung secara inheren. Misalnya, saat mengimplementasikan antarmuka di mana anggota tertentu tidak masuk akal untuk sebuah kelas. Ini terlihat seperti situasi yang serupa.sumber
Rupanya, Microsoft menggunakan
ArgumentException
untuk itu, seperti yang ditunjukkan pada contoh Expression.Lambda <> , Enum.TryParse <> atau Marshal.GetDelegateForFunctionPointer <> di bagian Pengecualian. Saya tidak dapat menemukan contoh yang menunjukkan sebaliknya, baik (meskipun mencari sumber referensi lokal untukTDelegate
danTEnum
).Jadi, saya pikir aman untuk mengasumsikan bahwa setidaknya dalam kode Microsoft itu adalah praktik umum yang digunakan
ArgumentException
untuk argumen tipe generik yang tidak valid selain dari yang variabel dasar. Mengingat bahwa deskripsi pengecualian di dokumen tidak membedakan keduanya, itu juga tidak terlalu berlebihan.Mudah-mudahan ini memutuskan pertanyaan itu sekali dan untuk selamanya.
sumber
TypeArgumentException
dariArgumentException
, hanya karena jenis argumen tidak biasa argumen.Saya akan menggunakan NotSupportedExpcetion.
sumber
Melempar pengecualian yang dibuat khusus harus selalu dilakukan dalam kasus apa pun yang meragukan. Pengecualian khusus akan selalu berfungsi, apa pun kebutuhan pengguna API. Pengembang dapat menangkap salah satu tipe pengecualian jika dia tidak peduli, tetapi jika pengembang membutuhkan penanganan khusus dia akan menjadi SOL.
sumber
Bagaimana jika mewarisi dari NotSupportedException. Meskipun saya setuju dengan @Mehrdad bahwa ini paling masuk akal, saya dengar pendapat Anda bahwa ini sepertinya tidak sesuai dengan sempurna. Jadi, mewarisi dari NotSupportedException, dan dengan begitu orang yang melakukan pengkodean terhadap API Anda masih bisa menangkap NotSupportedException.
sumber
Saya selalu berhati-hati dalam menulis pengecualian khusus, semata-mata karena pengecualian tersebut tidak selalu didokumentasikan dengan jelas dan menyebabkan kebingungan jika tidak dinamai dengan benar.
Dalam hal ini saya akan melempar ArgumentException untuk kegagalan pemeriksaan bendera. Semuanya tergantung pada preferensi. Beberapa standar pengkodean yang telah saya lihat sejauh untuk menentukan jenis pengecualian mana yang harus dilemparkan dalam skenario seperti ini.
Jika pengguna mencoba untuk mengirimkan sesuatu yang bukan enum maka saya akan melempar InvalidOperationException.
Edit:
Yang lain mengangkat poin menarik bahwa ini tidak didukung. Satu-satunya perhatian saya dengan NotSupportedException adalah bahwa secara umum itu adalah pengecualian yang dilemparkan ketika "materi gelap" telah dimasukkan ke sistem, atau dengan kata lain, "Metode ini harus masuk ke sistem pada antarmuka ini, tetapi kami menang hidupkan sampai versi 2.4 "
Saya juga melihat NotSupportedExceptions dilemparkan sebagai pengecualian lisensi "Anda menjalankan versi gratis dari perangkat lunak ini, fungsi ini tidak didukung".
Edit 2:
Kemungkinan lain:
Pengecualian dilontarkan saat menggunakan argumen tidak valid yang merupakan enumerator.
sumber
LicensingException
kelas yang diwarisiInvalidOperationException
.Saya juga akan memilih InvalidOperationException. Saya melakukan diagram alur (tidak lengkap) pada pedoman melempar pengecualian NET berdasarkan pada Pedoman Desain Kerangka 2nd Ed. beberapa waktu yang lalu jika ada yang tertarik.
sumber