Apakah mungkin untuk mendefinisikan konversi enum secara implisit dalam c #?
sesuatu yang bisa mencapai ini?
public enum MyEnum
{
one = 1, two = 2
}
MyEnum number = MyEnum.one;
long i = number;
Jika tidak, mengapa tidak?
c#
enums
implicit-conversion
implicit
Adam Naylor
sumber
sumber
enum YesNo {Yes, No}
yang secara implisit dapat dikonversi menjadi bool.Jawaban:
Ada solusinya. Pertimbangkan yang berikut ini:
Di atas menawarkan konversi implisit:
Ini adalah pekerjaan yang agak lebih adil daripada mendeklarasikan enum normal (meskipun Anda dapat mengubah beberapa hal di atas menjadi kelas dasar umum umum). Anda dapat melangkah lebih jauh dengan meminta kelas dasar mengimplementasikan IComparable & IEquatable, serta menambahkan metode untuk mengembalikan nilai DescriptionAttributes, nama yang dideklarasikan, dll., Dll.
Saya menulis kelas dasar (RichEnum <>) untuk menangani sebagian besar pekerjaan kasar, yang memudahkan deklarasi enum di atas ke:
Kelas dasar (RichEnum) tercantum di bawah ini.
sumber
Anda tidak dapat melakukan konversi tersirat (kecuali untuk nol), dan Anda tidak dapat menulis metode contoh Anda sendiri - namun, Anda mungkin dapat menulis metode ekstensi Anda sendiri:
Ini tidak memberi Anda banyak, meskipun (dibandingkan dengan hanya melakukan pemeran eksplisit).
Salah satu waktu utama saya melihat orang menginginkan ini adalah untuk melakukan
[Flags]
manipulasi melalui obat generik - yaitubool IsFlagSet<T>(T value, T flag);
metode. Sayangnya, C # 3.0 tidak mendukung operator pada obat generik, tetapi Anda dapat menyiasati hal ini menggunakan hal-hal seperti ini , yang membuat operator sepenuhnya tersedia dengan obat generik.sumber
sumber
static class
saya kira. Tidak ada untungnya berdebat untuk kedua kasus dalamIL
kode akhir .Saya mengadaptasi baseclass generik yang sangat baik dari Markus RichEnum.
Pemasangan
Kudos to Mark untuk ide + implementasi indah, ini untuk Anda semua:
Contoh penggunaan yang saya jalankan di mono:
Memproduksi output
Catatan: mono 2.6.7 membutuhkan pemeran ekstra eksplisit yang tidak diperlukan saat menggunakan mono 2.8.2 ...
sumber
FirstOrDefault
, untuk menghindari asumsi hanya ada satu atribut). Apakah mengasumsikan hal-hal seperti itu adalah 'ide yang baik' (atau yang buruk , dalam hal ini) tentu saja, tergantung pada konteksnyaTDerived instance = (TDerived)field.GetValue(null);
hasilinstance
menjadinull
. Tampaknya runtime Mono harus memiliki urutan inisialisasi tipe yang berbeda dari .NET yang memungkinkan ini berfungsi. Membingungkan! Sebagai gantinya saya harus memindahkan kode itu ke metode statis dan menyebutnya dari tipe initializer di subclass.Anda tidak dapat mendeklarasikan konversi implisit pada tipe enum, karena mereka tidak dapat menentukan metode. Kata kunci implisit C # mengkompilasi menjadi metode yang dimulai dengan 'op_', dan itu tidak akan berfungsi dalam kasus ini.
sumber
Anda mungkin bisa, tetapi tidak untuk enum (Anda tidak dapat menambahkan metode untuk itu). Anda bisa menambahkan konversi implisit ke kelas Anda sendiri untuk memungkinkan enum dikonversi ke dalamnya,
Pertanyaannya adalah mengapa?
Secara umum. Net menghindari (dan Anda juga harus) setiap konversi implisit di mana data dapat hilang.
sumber
Jika Anda menetapkan basis enum sebagai panjang maka Anda dapat melakukan konversi eksplisit. Saya tidak tahu apakah Anda dapat menggunakan konversi tersirat karena enum tidak dapat memiliki metode yang ditentukan pada mereka.
Perlu diketahui juga bahwa enumerasi yang tidak diinisialisasi akan default ke nilai 0, atau item pertama - jadi dalam situasi di atas mungkin akan lebih baik untuk mendefinisikan
zero = 0
juga.sumber
: long
sini; konversi eksplisit akan bekerja dengan baik tanpa itu. Satu-satunya konversi implisit legal adalah nol.enum sebagian besar tidak berguna bagi saya karena ini, OP.
Saya akhirnya melakukan hal-hal yang berhubungan dengan foto setiap saat:
solusi sederhana
Contoh masalah klasik adalah set VirtualKey untuk mendeteksi penekanan tombol.
Masalahnya di sini adalah Anda tidak dapat mengindeks array dengan enum karena tidak dapat secara implisit mengkonversi enum ke ushort (meskipun kami bahkan mendasarkan enum pada ushort)
dalam konteks khusus ini, enum dihancurkan oleh struktur data berikut. . . .
sumber
Saya telah mengatasi masalah dengan jawaban sehe ketika menjalankan kode pada MS .net (non-Mono). Bagi saya secara khusus masalah terjadi pada .net 4.5.1 tetapi versi lain juga terpengaruh.
Masalah
mengakses
public static TDervied MyEnumValue
dengan refleksi (viaFieldInfo.GetValue(null)
tidak tidak initialize kata lapangan.Penanganannya
Alih-alih menugaskan nama untuk
TDerived
instance pada penginisialisasi statisRichEnum<TValue, TDerived>
ini dilakukan malas pada akses pertamaTDerived.Name
. Kode:yang - dalam kasus saya - didasarkan pada
EquatableBase<T>
:Catatan
Kode di atas tidak memasukkan semua fitur jawaban asli Markus !
Terima kasih
Terima kasih kepada Mark karena menyediakan
RichEnum
implementasinya dan terima kasih kepada Sehe karena telah memberikan beberapa perbaikan!sumber
Saya menemukan solusi yang lebih mudah diambil dari sini /codereview/7566/enum-vs-int-wrapper-struct Saya menyisipkan kode di bawah ini dari tautan itu kalau-kalau itu tidak berfungsi di masa depan.
sumber
Saya membuat utilitas ini untuk membantu saya mengonversi Enum ke PrimitiveEnum dan PrimitiveEnum menjadi
byte, sbyte, short, ushort, int, uint, long, or ulong
.Jadi, ini secara teknis mengkonversi enum apa pun ke nilai primitifnya.
Lihat komit di https://github.com/McKabue/McKabue.Extentions.Utility/blob/master/src/McKabue.Extentions.Utility/Enums/PrimitiveEnum.cs
sumber
uint
s yang biasanya dibuat oleh permainan itu sendirienum
, tetapi kerangka itu tidak tahu apa-apa tentangnya. Harus(uint)
ketika memanggil kerangka kerja itu menyakitkan. Ide Anda mundur bekerja dengan sempurna. Alih-alihstruct
menyimpanEnum
, saya punyastruct IdNumber
yang menyimpanuint
tetapi secara implisit mengkonversi dariEnum
permainan menggunakan. Alih-alih mengetik param kerangka sebagaiuint
, saya bisa mengetiknyaIdNumber
, dan kerangka kerja secara internal dapat membagikannya secara efisien, bahkan melakukan operasi integral pada mereka.Memperkenalkan konversi implisit untuk tipe enum akan merusak keamanan tipe, jadi saya tidak akan merekomendasikan untuk melakukannya. Mengapa Anda ingin melakukan itu? Satu-satunya use case untuk ini yang saya lihat adalah ketika Anda ingin meletakkan nilai enum ke dalam struktur dengan tata letak yang telah ditentukan. Tetapi bahkan kemudian, Anda dapat menggunakan tipe enum dalam struktur dan hanya memberi tahu Marshaller apa yang harus ia lakukan dengan ini.
sumber