Saya memiliki enum di namespace tingkat rendah. Saya ingin memberikan kelas atau enum di namespace tingkat menengah yang "mewarisi" enum tingkat rendah.
namespace low
{
public enum base
{
x, y, z
}
}
namespace mid
{
public enum consume : low.base
{
}
}
Saya berharap ini mungkin, atau mungkin beberapa jenis kelas yang dapat menggantikan konsumsi enum yang akan memberikan lapisan abstraksi untuk enum, tetapi masih membiarkan instance kelas itu mengakses enum.
Pikiran?
EDIT: Salah satu alasan saya tidak hanya beralih ke const di kelas adalah bahwa enum tingkat rendah diperlukan oleh layanan yang harus saya konsumsi. Saya telah diberi WSDL dan XSD, yang mendefinisikan struktur sebagai enum. Layanan tidak dapat diubah.
Jawaban:
Ini tidak mungkin. Enum tidak dapat diwarisi dari enum lainnya. Sebenarnya semua enum harus benar-benar mewarisi dari
System.Enum
. C # memungkinkan sintaks untuk mengubah representasi yang mendasari nilai enum yang tampak seperti warisan, tetapi dalam kenyataannya mereka masih mewarisi dari System.enum.Lihat bagian 8.5.2 dari spesifikasi CLI untuk detail selengkapnya. Informasi yang relevan dari spesifikasi
System.Enum
sumber
switch
situasi.Anda dapat mencapai apa yang Anda inginkan dengan kelas:
Sekarang Anda dapat menggunakan kelas-kelas ini sama seperti ketika mereka enum:
Pembaruan (setelah pembaruan pertanyaan Anda):
Jika Anda menetapkan nilai int yang sama ke konstanta seperti yang didefinisikan dalam enum yang ada, maka Anda dapat melemparkan antara enum dan konstanta, misalnya:
sumber
Enum.GetValues(typeof(MyEnum)
void Test() { foreach (System.Reflection.PropertyInfo pi in typeof(Consume).GetProperties()) { Console.WriteLine(pi.Name); } }
Jawaban singkatnya adalah tidak. Anda bisa bermain sedikit, jika Anda mau:
Anda selalu dapat melakukan sesuatu seperti ini:
Tapi, itu tidak berfungsi dengan baik karena Base.A! = Mengkonsumsi
Anda selalu dapat melakukan hal seperti ini:
Untuk melintasi antara Basis dan Konsumsi ...
Anda juga bisa melemparkan nilai-nilai enum sebagai int, dan membandingkannya sebagai int bukan enum, tetapi jenis itu juga menyebalkan.
Metode ekstensi kembali harus ketik cor itu ketik T.
sumber
Base.A == (Base)Consume.A
int
akan lebih masuk akal. Kapan sebuah enum memiliki bagian fraksional!?!?!Solusi di atas menggunakan kelas dengan konstanta int tidak memiliki tipe keselamatan. Yaitu Anda bisa menemukan nilai-nilai baru yang sebenarnya tidak didefinisikan di kelas. Selain itu tidak mungkin misalnya untuk menulis metode yang mengambil salah satu dari kelas-kelas ini sebagai input.
Anda harus menulis
Namun, ada solusi berbasis kelas dari masa lalu Jawa, ketika tidak ada enum yang tersedia. Ini memberikan perilaku yang hampir seperti enum. Satu-satunya peringatan adalah bahwa konstanta ini tidak dapat digunakan dalam pernyataan switch.
sumber
object
akan membuat nilai berbeda untuk setiap instantiation dari perakitan sehingga mereka tidak bisa serial.Mengabaikan fakta bahwa basis adalah kata yang dilindungi undang-undang, Anda tidak dapat melakukan pewarisan enum.
Hal terbaik yang dapat Anda lakukan adalah sesuatu seperti itu:
Karena semuanya adalah tipe basis yang sama (yaitu: int), Anda dapat menetapkan nilai dari instance dari satu tipe ke yang lainnya yang dilemparkan. Tidak ideal tetapi berhasil.
sumber
Saya tahu jawaban ini agak terlambat tetapi inilah yang akhirnya saya lakukan:
Maka saya dapat melakukan hal-hal seperti:
sumber
Inilah yang saya lakukan. Apa yang saya lakukan berbeda adalah menggunakan nama dan
new
kata kunci yang sama pada "mengkonsumsi"enum
. Karena namaenum
itu sama, Anda bisa menggunakannya tanpa pikir panjang dan itu akan benar. Plus Anda mendapatkan Intellisense. Anda hanya perlu berhati-hati saat mengaturnya agar nilai-nilai disalin dari pangkalan dan tetap disinkronkan. Anda dapat membantu itu bersama dengan komentar kode. Ini adalah alasan lain mengapa dalam database ketika menyimpanenum
nilai, saya selalu menyimpan string, bukan nilai. Karena jika Anda menggunakan peningkatan nilai integer yang ditetapkan secara otomatis, nilai itu dapat berubah seiring waktu.sumber
SmallMedium = 100,
), Sehingga Anda dapat menjaga kompatibilitas dengan versi lama dari perangkat lunak Anda ketika Anda menambahkan nilai-nilai baru di kelas dasar. Misalnya, menambahkanHuge
ukuran di enum dasar Anda akan menetapkan4
nilainya, tetapi4
sudah diambilSmallMedium
di kelas turunan.Huge
di kelas dasar akan perluHuge
di subclass sebelumSmallMedium
BaseBall
mungkin bukan nama yang paling cerdas di sini. Ini membingungkan. Karena bisbol sebenarnya adalah sesuatu. Jika Anda melewatkan bahwa ini hanya kelas dasar untuk bola, terlihat sangat aneh bahwa bola voli mewarisi dari baseball yang secara fisik lebih kecil :). Saran saya adalah gunakan sajaBall
Solusi alternatif
Di perusahaan saya, kami menghindari "melompati proyek" untuk mencapai proyek tingkat rendah yang tidak umum. Misalnya, lapisan presentasi / API kami hanya dapat mereferensikan lapisan domain kami, dan lapisan domain hanya dapat mereferensikan lapisan data.
Namun, ini merupakan masalah ketika ada enum yang perlu direferensikan oleh presentasi dan lapisan domain.
Inilah solusi yang telah kami terapkan (sejauh ini). Ini adalah solusi yang cukup bagus dan bekerja dengan baik untuk kita. Jawaban lain mengenai semua ini.
Premis dasarnya adalah bahwa enum tidak dapat diwarisi - tetapi kelas dapat. Begitu...
Kemudian, untuk "mewarisi" enum di proyek tingkat yang lebih tinggi ...
Ini memiliki tiga keunggulan nyata ...
Untuk referensi enum di proyek pertama , Anda bisa menggunakan awalan kelas: BaseEnums.StatusType.Pending atau tambahkan "using static BaseEnums;"pernyataan untuk usings Anda.
Namun dalam proyek kedua ketika berhadapan dengan kelas yang diwarisi, saya tidak bisa mendapatkan pendekatan "using static ..." untuk bekerja, jadi semua referensi ke "enum yang diwariskan" akan diawali dengan kelas, misalnya SubEnums.StatusType.Pending . Jika ada yang datang dengan cara untuk memungkinkan "menggunakan statis" untuk digunakan dalam proyek kedua, beri tahu saya.
Saya yakin ini bisa diubah untuk membuatnya lebih baik - tetapi ini benar-benar berfungsi dan saya telah menggunakan pendekatan ini dalam proyek-proyek yang sedang berjalan.
Harap pilih ini jika Anda merasa terbantu.
sumber
Saya juga ingin membebani Enums dan menciptakan campuran jawaban 'Tujuh' di halaman ini dan jawaban 'Merlyn Morgan-Graham' pada pos duplikat ini , ditambah beberapa perbaikan.
Keuntungan utama dari solusi saya daripada yang lain:
Ini adalah solusi out-of-the-box dan dapat langsung dimasukkan ke dalam proyek Anda. Ini dirancang untuk kebutuhan saya, jadi jika Anda tidak suka beberapa bagian, ganti saja dengan kode Anda sendiri.
Pertama, ada kelas dasar
CEnum
yang harus diwarisi dari semua enum khusus. Ini memiliki fungsi dasar, mirip denganEnum
tipe .net :Kedua, berikut adalah 2 kelas Enum yang diturunkan. Semua kelas turunan membutuhkan beberapa metode dasar untuk bekerja seperti yang diharapkan. Itu selalu kode boilerplate yang sama; Saya belum menemukan cara untuk melakukan outsourcing ke kelas dasar. Kode tingkat pewarisan pertama sedikit berbeda dari semua tingkatan selanjutnya.
Kelas telah berhasil diuji dengan kode follwing:
sumber
Enum bukan kelas yang sebenarnya, bahkan jika mereka terlihat seperti itu. Secara internal, mereka diperlakukan sama seperti tipe yang mendasarinya (secara default Int32). Oleh karena itu, Anda hanya dapat melakukan ini dengan "menyalin" nilai tunggal dari satu enum ke yang lain dan melemparkannya ke nomor bilangan bulat untuk membandingkannya untuk kesetaraan.
sumber
Enum tidak dapat diturunkan dari enum lain, tetapi hanya dari int, uint, pendek, ushort, panjang, ulong, byte dan sbyte.
Seperti kata Pascal, Anda dapat menggunakan nilai atau konstanta enum lain untuk menginisialisasi nilai enum, tetapi hanya itu saja.
sumber
solusi lain yang mungkin:
HTH
sumber
Ini tidak mungkin (seperti @JaredPar sudah sebutkan). Mencoba menerapkan logika untuk mengatasi ini adalah praktik yang buruk. Jika Anda memiliki
base class
yang memilikienum
, Anda harus membuat daftar semua kemungkinanenum-values
sana, dan implementasi kelas harus bekerja dengan nilai-nilai yang diketahuinya.Misalkan Anda memiliki kelas dasar
BaseCatalog
, dan memilikienum ProductFormats
(Digital
,Physical
). Maka Anda dapat memilikiMusicCatalog
atauBookCatalog
yang dapat mengandung keduanyaDigital
danPhysical
produk, tetapi jika kelasnya adalahClothingCatalog
, itu seharusnya hanya berisiPhysical
produk.sumber
Saya sadar saya agak terlambat ke pesta ini, tapi ini dua sen saya.
Kita semua jelas bahwa warisan Enum tidak didukung oleh kerangka kerja. Beberapa solusi yang sangat menarik telah disarankan di utas ini, tetapi tidak ada yang merasa seperti apa yang saya cari, jadi saya harus mencobanya sendiri.
Memperkenalkan: ObjectEnum
Anda dapat memeriksa kode dan dokumentasi di sini: https://github.com/dimi3tron/ObjectEnum .
Dan paketnya di sini: https://www.nuget.org/packages/ObjectEnum
Atau cukup instal:
Install-Package ObjectEnum
Pendeknya,
ObjectEnum<TEnum>
bertindak sebagai pembungkus untuk enum apa pun. Dengan mengesampingkan GetDefinedValues () dalam subclass, seseorang dapat menentukan nilai enum mana yang valid untuk kelas spesifik ini.Sejumlah kelebihan operator telah ditambahkan untuk membuat
ObjectEnum<TEnum>
instance berperilaku seolah-olah itu adalah instance dari enum yang mendasari, dengan mengingat batasan nilai yang ditentukan. Ini berarti Anda dapat dengan mudah membandingkan instance ke nilai int atau enum, dan dengan demikian menggunakannya dalam casing atau kondisional lainnya.Saya ingin merujuk pada repo github yang disebutkan di atas untuk contoh dan info lebih lanjut.
Saya harap Anda menemukan ini berguna. Jangan ragu untuk berkomentar atau membuka masalah di github untuk pemikiran atau komentar lebih lanjut.
Berikut adalah beberapa contoh singkat tentang apa yang dapat Anda lakukan dengan
ObjectEnum<TEnum>
:sumber
Anda dapat melakukan pewarisan di enum, namun terbatas hanya pada tipe berikut. int, uint, byte, sbyte, pendek, ushort, panjang, ulong
Misalnya
sumber