Saya memiliki enumerasi berikut:
public enum AuthenticationMethod
{
FORMS = 1,
WINDOWSAUTHENTICATION = 2,
SINGLESIGNON = 3
}
Namun masalahnya adalah bahwa saya memerlukan kata "BENTUK" ketika saya meminta AuthenticationMethod.FORMS dan bukan id 1.
Saya telah menemukan solusi berikut untuk masalah ini ( tautan ):
Pertama, saya perlu membuat atribut khusus yang disebut "StringValue":
public class StringValue : System.Attribute
{
private readonly string _value;
public StringValue(string value)
{
_value = value;
}
public string Value
{
get { return _value; }
}
}
Kemudian saya dapat menambahkan atribut ini ke enumerator saya:
public enum AuthenticationMethod
{
[StringValue("FORMS")]
FORMS = 1,
[StringValue("WINDOWS")]
WINDOWSAUTHENTICATION = 2,
[StringValue("SSO")]
SINGLESIGNON = 3
}
Dan tentu saja saya perlu sesuatu untuk mengambil StringValue itu:
public static class StringEnum
{
public static string GetStringValue(Enum value)
{
string output = null;
Type type = value.GetType();
//Check first in our cached results...
//Look for our 'StringValueAttribute'
//in the field's custom attributes
FieldInfo fi = type.GetField(value.ToString());
StringValue[] attrs =
fi.GetCustomAttributes(typeof(StringValue),
false) as StringValue[];
if (attrs.Length > 0)
{
output = attrs[0].Value;
}
return output;
}
}
Bagus sekarang saya punya alat untuk mendapatkan nilai string untuk enumerator. Saya kemudian dapat menggunakannya seperti ini:
string valueOfAuthenticationMethod = StringEnum.GetStringValue(AuthenticationMethod.FORMS);
Oke sekarang semua ini bekerja seperti pesona tetapi saya merasa banyak pekerjaan. Saya bertanya-tanya apakah ada solusi yang lebih baik untuk ini.
Saya juga mencoba sesuatu dengan kamus dan properti statis tetapi itu juga tidak lebih baik.
this
di depanEnum
dalam metode statis Anda. Maka Anda bisa melakukannyaAuthenticationMethod.Forms.GetStringValue();
Jawaban:
Cobalah tipe-safe-enum pattern.
Pembaruan Konversi tipe eksplisit (atau implisit) dapat dilakukan oleh
menambahkan bidang statis dengan pemetaan
mengisi pemetaan ini di konstruktor contoh
dan menambahkan operator konversi tipe yang ditentukan pengguna
sumber
Gunakan metode
seperti dalam (Asumsikan
Shipper
adalah Enum yang ditentukan)Ada banyak metode statis lainnya di kelas Enum yang layak diselidiki juga ...
sumber
Anda dapat merujuk nama daripada nilainya dengan menggunakan ToString ()
Dokumentasi di sini:
http://msdn.microsoft.com/en-us/library/16c1xs4z.aspx
... dan jika Anda memberi nama enum Anda dalam Pascal Case (seperti yang saya lakukan - seperti ThisIsMyEnumValue = 1 dll.) maka Anda dapat menggunakan regex yang sangat sederhana untuk mencetak formulir ramah:
yang dapat dengan mudah dipanggil dari sembarang string:
Output:
Itu menghemat menjalankan semua jalan di sekitar rumah-rumah menciptakan atribut khusus dan melampirkannya ke enum Anda atau menggunakan tabel pencarian untuk mengawinkan nilai enum dengan string yang ramah dan yang terbaik dari semua itu mengelola sendiri dan dapat digunakan pada string Pascal Case apa pun yang tak terbatas lebih dapat digunakan kembali. Tentu saja, itu tidak memungkinkan Anda untuk memiliki nama ramah yang berbeda dari enum yang disediakan oleh solusi Anda.
Saya suka solusi orisinal Anda meskipun untuk skenario yang lebih kompleks. Anda bisa mengambil solusi Anda satu langkah lebih jauh dan menjadikan GetStringValue Anda sebagai metode ekstensi enum Anda dan kemudian Anda tidak perlu referensi seperti StringEnum. DapatkanStringValue ...
Anda kemudian dapat mengaksesnya dengan mudah langsung dari instance enum Anda:
sumber
"(?!^)([^A-Z])([A-Z])", "$1 $2"
. JadiHereIsATEST
menjadiHere Is ATEST
.Sayangnya refleksi untuk mendapatkan atribut pada enum cukup lambat:
Lihat pertanyaan ini: Adakah yang tahu cara cepat untuk mendapatkan atribut khusus pada nilai enum?
Ini
.ToString()
juga cukup lambat pada enum.Anda dapat menulis metode ekstensi untuk enum:
Ini tidak bagus, tetapi akan cepat dan tidak memerlukan refleksi untuk atribut atau nama bidang.
Pembaruan C # 6
Jika Anda dapat menggunakan C # 6 maka
nameof
operator baru berfungsi untuk enum, sehingganameof(MyEnum.WINDOWSAUTHENTICATION)
akan dikonversi menjadi"WINDOWSAUTHENTICATION"
pada waktu kompilasi , menjadikannya cara tercepat untuk mendapatkan nama enum.Perhatikan bahwa ini akan mengonversi enum eksplisit ke konstanta inline, jadi itu tidak berfungsi untuk enum yang Anda miliki dalam variabel. Begitu:
Tapi...
sumber
Saya menggunakan metode ekstensi:
Sekarang hiasi
enum
dengan:Saat Anda menelepon
AuthenticationMethod.FORMS.ToDescription()
kamu akan mendapatkan"FORMS"
.sumber
using System.ComponentModel;
Juga, metode ini hanya berfungsi jika Anda ingin nilai String sama dengan nama Enum. OP menginginkan nilai yang berbeda.AuthenticationMethod.FORMS.ToDescription()
?Cukup gunakan
ToString()
metode iniUntuk referensi string
Tomato
, cukup gunakansumber
.ToString()
nilai berbeda dari nilai ramah pengguna yang Anda butuhkan.any fruit = any.Tomato;
string tomato = fruit.ToString();
Solusi yang sangat sederhana untuk ini dengan .Net 4.0 dan di atasnya. Tidak diperlukan kode lain.
Untuk mendapatkan string tentang cukup gunakan:
atau
Nilai akan "Aktif" atau "Diarsipkan".
Untuk melihat format string yang berbeda ("f" dari atas) saat memanggil
Enum.ToString
lihat halaman Enumeration Format Strings inisumber
Saya menggunakan atribut Deskripsi dari namespace System.ComponentModel. Cukup hiasi enum dan kemudian gunakan kode ini untuk mengambilnya:
Sebagai contoh:
Kode ini dapat digunakan untuk enum di mana Anda tidak memerlukan "Nama yang ramah" dan hanya akan mengembalikan .ToString () dari enum.
sumber
Saya sangat menyukai jawaban Jakub Šturc, tetapi kekurangannya adalah Anda tidak dapat menggunakannya dengan pernyataan sakelar kasus. Inilah versi yang sedikit dimodifikasi dari jawabannya yang dapat digunakan dengan pernyataan pergantian:
Jadi Anda mendapatkan semua manfaat dari jawaban Jakub Šturc, ditambah kita dapat menggunakannya dengan pernyataan pergantian seperti:
sumber
public static int nextAvailable { get; private set; }
kemudian di konstruktorthis.Value = nextAvailable++;
=
operator terlalu banyak untuk memungkinkan pergantian bekerja? Saya melakukan ini di VB dan sekarang dapat menggunakannya dalamselect case
pernyataan.Saya menggunakan kombinasi beberapa saran di atas, dikombinasikan dengan caching. Sekarang, saya mendapat ide dari beberapa kode yang saya temukan di suatu tempat di internet, tetapi saya tidak dapat mengingat di mana saya mendapatkannya atau menemukannya. Jadi, jika ada orang yang menemukan sesuatu yang mirip, silakan berkomentar dengan atribusi.
Lagi pula, penggunaannya melibatkan konverter tipe, jadi jika Anda mengikat ke UI itu 'hanya berfungsi'. Anda dapat memperluas dengan pola Jakub untuk pencarian kode cepat dengan menginisialisasi dari konverter tipe ke metode statis.
Penggunaan basis akan terlihat seperti ini
Kode untuk konverter tipe enum kustom berikut:
}
sumber
Dalam pertanyaan Anda, Anda tidak pernah mengatakan bahwa Anda benar-benar membutuhkan nilai numerik enum di mana saja.
Jika Anda tidak dan hanya perlu enum tipe string (yang bukan tipe integral sehingga tidak bisa menjadi basis enum) di sini adalah caranya:
Anda dapat menggunakan sintaks yang sama dengan enum untuk referensi
Ini akan sedikit lebih lambat dibandingkan dengan nilai numerik (membandingkan string bukan angka) tetapi di sisi positifnya ia tidak menggunakan refleksi (lambat) untuk mengakses string.
sumber
Bagaimana saya memecahkan ini sebagai metode ekstensi:
Enum:
Penggunaan (di mana o.OrderType adalah properti dengan nama yang sama dengan enum):
Yang memberi saya serangkaian "Kartu Baru" atau "Muat Ulang" alih-alih nilai aktual NewCard dan Isi Ulang.
sumber
Pembaruan: Mengunjungi halaman ini, 8 tahun kemudian, setelah tidak menyentuh C # untuk waktu yang lama, sepertinya jawaban saya bukan lagi solusi terbaik. Saya sangat suka solusi konverter diikat dengan atribut-fungsi.
Jika Anda membaca ini, pastikan Anda juga memeriksa jawaban lain.
(petunjuk: mereka di atas yang ini)
Seperti kebanyakan dari Anda, saya sangat menyukai jawaban yang dipilih oleh Jakub Šturc , tetapi saya juga sangat benci menyalin kode tempel, dan mencoba melakukannya sesedikit mungkin.
Jadi saya memutuskan saya ingin kelas EnumBase dari mana sebagian besar fungsi diwarisi / bawaan, membuat saya fokus pada konten alih-alih perilaku.
Masalah utama dengan pendekatan ini didasarkan pada fakta bahwa meskipun nilai-nilai Enum adalah instance tipe-aman, interaksinya adalah dengan implementasi Statis dari tipe Kelas Enum. Jadi dengan sedikit bantuan sihir generik, saya pikir saya akhirnya mendapatkan campuran yang benar. Semoga seseorang menemukan ini berguna seperti yang saya lakukan.
Saya akan mulai dengan contoh Jakub, tetapi menggunakan warisan dan obat generik:
Dan di sini adalah kelas dasar:
sumber
Saya setuju dengan Keith, tetapi saya tidak dapat memilih (belum).
Saya menggunakan metode statis dan pernyataan swith untuk mengembalikan apa yang saya inginkan. Dalam database saya menyimpan tinyint dan kode saya hanya menggunakan enum yang sebenarnya, jadi string adalah untuk persyaratan UI. Setelah banyak pengujian, ini menghasilkan kinerja terbaik dan sebagian besar kontrol atas output.
Namun, oleh beberapa akun, ini mengarah pada kemungkinan mimpi buruk pemeliharaan dan beberapa bau kode. Saya mencoba untuk mengawasi enum yang panjang dan banyak enum, atau yang sering berubah. Kalau tidak, ini merupakan solusi yang bagus untuk saya.
sumber
Jika Anda datang ke sini mencari untuk menerapkan "Enum" sederhana tetapi yang nilainya adalah string bukan ints, berikut adalah solusi paling sederhana:
Penerapan:
sumber
static readonly
.Ketika saya dihadapkan dengan masalah ini, ada beberapa pertanyaan yang saya coba cari jawabannya terlebih dahulu:
Cara paling sederhana untuk melakukan ini adalah dengan
Enum.GetValue
(dan mendukung penggunaan trip-trippingEnum.Parse
). Sering juga layak untuk membangunTypeConverter
, seperti yang disarankan Steve Mitcham, untuk mendukung pengikatan UI. (Tidak perlu untuk membangunTypeConverter
ketika Anda menggunakan lembar properti, yang merupakan salah satu hal yang menyenangkan tentang lembar properti. Meskipun tuan tahu mereka memiliki masalah sendiri.)Secara umum, jika jawaban atas pertanyaan di atas menunjukkan bahwa tidak akan berhasil, langkah saya selanjutnya adalah membuat dan mengisi statis
Dictionary<MyEnum, string>
, atau mungkin aDictionary<Type, Dictionary<int, string>>
. Saya cenderung melewatkan langkah mendekorasi-kode-dengan-atribut sementara karena apa yang biasanya muncul selanjutnya adalah perlunya mengubah nilai-nilai ramah setelah penyebaran (sering, tetapi tidak selalu, karena lokalisasi).sumber
Saya ingin memposting ini sebagai komentar untuk posting yang dikutip di bawah ini tetapi tidak bisa karena saya tidak punya cukup perwakilan - jadi tolong jangan turunkan suara. Kode berisi kesalahan dan saya ingin menunjukkan ini kepada individu yang mencoba menggunakan solusi ini:
seharusnya
Brillant!
sumber
Varian saya
Kode terlihat agak jelek, tetapi penggunaan struct ini cukup presentatif.
Juga, saya pikir, jika banyak enum diperlukan, pembuatan kode (misalnya T4) dapat digunakan.
sumber
Pilihan 1:
lalu
Pilihan 2:
sumber
Jika Anda memikirkan masalah yang kami coba selesaikan, itu bukan enum yang kami butuhkan sama sekali. Kita membutuhkan objek yang memungkinkan sejumlah nilai dikaitkan dengan satu sama lain; dengan kata lain, untuk mendefinisikan kelas.
Pola enum yang aman untuk tipe Jakub Šturc adalah pilihan terbaik yang saya lihat di sini.
Lihat itu:
sumber
bagi saya, pendekatan pragmatis adalah kelas di dalam kelas, contoh:
sumber
Saya membuat kelas dasar untuk membuat enums bernilai string di .NET. Ini hanya satu file C # yang dapat Anda salin & tempel ke proyek Anda, atau instal melalui paket NuGet bernama StringEnum . GitHub Repo
<completitionlist>
. (Bekerja di C # dan VB)Instalasi:
.Net Standard 1.0
sehingga berjalan pada.Net Core
> = 1.0,.Net Framework
> = 4.5,Mono
> = 4.6, dll.sumber
Inilah cara lain untuk menyelesaikan tugas mengaitkan string dengan enum:
Metode ini disebut seperti ini:
Anda dapat mengelompokkan enum terkait di struct mereka sendiri. Karena metode ini menggunakan tipe enum, Anda dapat menggunakan Intellisense untuk menampilkan daftar enum saat melakukan
GetString()
panggilan.Anda secara opsional dapat menggunakan operator baru pada
DATABASE
struct. Tidak menggunakannya berarti stringList
tidak dialokasikan sampaiGetString()
panggilan pertama dilakukan.sumber
Banyak jawaban bagus di sini tetapi dalam kasus saya tidak menyelesaikan apa yang saya inginkan dari "string enum", yaitu:
1,2 & 4 sebenarnya dapat diselesaikan dengan C # Typedef dari suatu string (karena string dapat diganti di c #)
3 dapat diselesaikan dengan string const statis. Jadi, jika Anda memiliki kebutuhan yang sama, ini adalah pendekatan paling sederhana:
Ini memungkinkan misalnya:
dan
Di mana CreateType dapat dipanggil dengan string atau tipe. Namun downside adalah bahwa setiap string secara otomatis adalah enum yang valid , ini dapat dimodifikasi tetapi kemudian akan memerlukan semacam fungsi init ... atau mungkin membuat mereka secara eksplisit melemparkan internal?
Sekarang jika nilai int penting bagi Anda (mungkin untuk kecepatan perbandingan), Anda dapat menggunakan beberapa ide dari Jakub Šturc jawaban yang fantastis dan melakukan sesuatu yang sedikit gila, ini adalah tikaman saya untuk itu:
tapi tentu saja "Jenis bob = 4;" akan menjadi tidak berarti kecuali Anda menginisialisasi mereka terlebih dahulu yang akan semacam mengalahkan intinya ...
Namun dalam teori, TypeA == TypeB akan lebih cepat ...
sumber
Jika saya memahami Anda dengan benar, Anda cukup menggunakan .ToString () untuk mengambil nama enum dari nilai (Anggap sudah dilemparkan sebagai Enum); Jika Anda memiliki int telanjang (katakanlah dari database atau sesuatu), Anda dapat terlebih dahulu melemparkannya ke enum. Kedua metode di bawah ini akan memberi Anda nama enum.
Perlu diingat, teknik kedua mengasumsikan Anda menggunakan int dan indeks Anda berdasarkan 1 (bukan berbasis 0). Fungsi GetNames juga cukup berat sebagai perbandingan, Anda menghasilkan seluruh array setiap kali dipanggil. Seperti yang Anda lihat pada teknik pertama, .ToString () sebenarnya disebut secara implisit. Kedua hal ini sudah disebutkan dalam jawaban tentu saja, saya hanya berusaha menjelaskan perbedaan di antara mereka.
sumber
pos lama tapi ...
Jawabannya sebenarnya sangat sederhana. Gunakan fungsi Enum.ToString ()
Ada 6 kelebihan fungsi ini, Anda dapat menggunakan Enum.Tostring ("F") atau Enum.ToString () untuk mengembalikan nilai string. Tidak perlu repot dengan hal lain. Ini Demo yang berfungsi
Perhatikan bahwa solusi ini mungkin tidak berfungsi untuk semua kompiler ( demo ini tidak berfungsi seperti yang diharapkan ) tetapi setidaknya ini berfungsi untuk kompiler terbaru.
sumber
berdasarkan pada MSDN: http://msdn.microsoft.com/en-us/library/cc138362.aspx
str akan menjadi nama bidang
sumber
Nah, setelah membaca semua hal di atas saya merasa bahwa orang-orang memiliki masalah rumit mengubah enumerator menjadi string. Saya menyukai gagasan memiliki atribut di atas bidang yang disebutkan tetapi saya pikir atribut tersebut terutama digunakan untuk Meta-data, tetapi dalam kasus Anda, saya pikir semua yang Anda butuhkan adalah semacam pelokalan.
Sekarang jika kita mencoba memanggil metode di atas kita dapat memanggilnya dengan cara ini
Yang perlu Anda lakukan hanyalah membuat file sumber yang berisi semua nilai enumerator dan string yang sesuai
Apa yang sebenarnya sangat baik tentang itu adalah bahwa itu akan sangat membantu jika Anda memerlukan aplikasi Anda untuk dilokalisasi, karena yang perlu Anda lakukan hanyalah membuat file sumber daya lain dengan bahasa baru Anda! dan Voe-la!
sumber
Ketika saya berada dalam situasi seperti itu saya mengusulkan solusi di bawah ini.
Dan sebagai kelas konsumsi Anda bisa memilikinya
Dan menggunakan kamus dua arah: Berdasarkan ini ( https://stackoverflow.com/a/255638/986160 ) dengan asumsi bahwa kunci akan dikaitkan dengan nilai tunggal dalam kamus dan mirip dengan ( https://stackoverflow.com/a / 255630/986160 ) tetapi sedikit lebih elegan. Kamus ini juga dapat dihitung dan Anda dapat bolak-balik dari int ke string. Anda juga tidak harus memiliki string apa pun di basis kode Anda dengan pengecualian kelas ini.
sumber
Untuk set string enum yang lebih besar, contoh-contoh yang tercantum dapat menjadi melelahkan. Jika Anda ingin daftar kode status, atau daftar enum berbasis string lainnya, sistem atribut menjengkelkan untuk digunakan, dan kelas statis dengan instance sendiri menjengkelkan untuk dikonfigurasi. Untuk solusi saya sendiri, saya menggunakan T4 templating untuk membuatnya lebih mudah untuk memiliki enum yang didukung string. Hasilnya mirip dengan cara kerja kelas HttpMethod.
Anda bisa menggunakannya seperti ini:
Anda mulai dengan file Enum.tt.
Kemudian, Anda menambahkan file StringEnum.ttinclude Anda.
Akhirnya, Anda mengkompilasi ulang file Enum.tt Anda dan hasilnya terlihat seperti ini:
sumber