Bagaimana Anda bisa menghitung enum
dalam C #?
Misalnya kode berikut tidak dikompilasi:
public enum Suit
{
Spades,
Hearts,
Clubs,
Diamonds
}
public void EnumerateAllSuitsDemoMethod()
{
foreach (Suit suit in Suit)
{
DoSomething(suit);
}
}
Dan itu memberikan kesalahan waktu kompilasi berikut:
'Suit' adalah 'tipe' tetapi digunakan seperti 'variabel'
Gagal pada Suit
kata kunci, yang kedua.
Jawaban:
Catatan : Para pemain untuk
(Suit[])
tidak sepenuhnya diperlukan, tetapi itu membuat kode 0,5 ns lebih cepat .sumber
enum.GetValues
. Anda harus menggunakan refleksi dalam hal ini.enum E {A = 0, B = 0}
.Enum.GetValues
menghasilkan dua nilai yang dikembalikan, meskipun mereka sama.E.A == E.B
itu benar, jadi tidak ada perbedaan. Jika Anda ingin nama individual, maka Anda harus mencarinyaEnum.GetNames
.Distinct
ekstensi Linq (sejak .NET 3.5), jadiforeach (var suit in ((Suit[])Enum.GetValues(typeof(Suit))).Distinct()) { }
.var
untuk tipe. Compiler akan membuat variabelObject
bukan enum. Daftar jenis enum secara eksplisit.Bagi saya sepertinya Anda benar-benar ingin mencetak nama masing-masing enum, daripada nilainya. Dalam hal ini
Enum.GetNames()
tampaknya pendekatan yang tepat.Omong-omong, menambahkan nilai bukanlah cara yang baik untuk menghitung nilai-nilai enum. Anda harus melakukan ini sebagai gantinya.
Saya akan menggunakan
Enum.GetValues(typeof(Suit))
sebagai gantinya.sumber
Enum.GetValues(typeof(Suits)).OfType<Suits>().ToArray()
. Dalam hal ini saya dapat mengulangi arraySuits
item enum, bukan string.Suits suit in Enum.GetValues(typeof(Suits))
?Saya membuat beberapa ekstensi untuk penggunaan enum yang mudah. Mungkin seseorang bisa menggunakannya ...
Enum itu sendiri harus didekorasi dengan FlagsAttribute :
sumber
Beberapa versi kerangka .NET tidak mendukung
Enum.GetValues
. Inilah solusi yang baik dari Ideas 2.0: Enum.GetValues dalam Compact Framework :Seperti halnya kode apa pun yang melibatkan refleksi , Anda harus mengambil langkah-langkah untuk memastikan itu berjalan hanya sekali dan hasilnya di-cache.
sumber
return type.GetFields().Where(x => x.IsLiteral).Select(x => x.GetValue(null)).Cast<Enum>();
Gunakan
Cast<T>
:Ini dia
IEnumerable<Suit>
,.sumber
from
klausa danforeach
deklarator header.Saya pikir ini lebih efisien daripada saran lain karena
GetValues()
tidak dipanggil setiap kali Anda memiliki loop. Itu juga lebih ringkas. Dan Anda mendapatkan kesalahan waktu kompilasi, bukan pengecualian runtime jikaSuit
bukanenum
.EnumLoop
memiliki definisi yang sepenuhnya generik ini:sumber
EnumLoop
dengan beberapa jenis yang bukan enum, ia akan dikompilasi dengan baik, tetapi melemparkan pengecualian saat runtime.Anda tidak akan mendapatkan
Enum.GetValues()
di Silverlight .Posting Blog Asli oleh Einar Ingebrigtsen :
sumber
where T: Enum
Solusi saya bekerja di .NET Compact Framework (3.5) dan mendukung pengecekan tipe pada waktu kompilasi :
T valueType = new T()
, saya akan senang melihat solusinya.Panggilan akan terlihat seperti ini:
sumber
T valueType = default(T)
?new()
T
. Juga, Anda tidak perlunew T()
sama sekali, Anda dapat memilih hanya bidang statis saja dan lakukan.GetValue(null)
. Lihat jawaban Aubrey.where T: Enum
Saya pikir Anda bisa menggunakannya
sumber
sumber
Saya pikir caching array akan mempercepatnya. Sepertinya Anda mendapatkan array baru (melalui refleksi) setiap saat. Agak:
Setidaknya itu sedikit lebih cepat, ja?
sumber
Tiga jalan:
Enum.GetValues(type)
// Sejak. NET 1.1, bukan di Silverlight atau .NET Compact Frameworktype.GetEnumValues()
// Hanya di .NET 4 dan di atasnyatype.GetFields().Where(x => x.IsLiteral).Select(x => x.GetValue(null))
// Bekerja di mana-manaSaya tidak yakin mengapa
GetEnumValues
diperkenalkan pada instance type. Sama sekali tidak bisa dibaca untuk saya.Memiliki kelas pembantu seperti
Enum<T>
apa yang paling mudah dibaca dan berkesan bagi saya:Sekarang Anda menelepon:
Seseorang juga dapat menggunakan semacam caching jika masalah kinerja, tapi saya tidak berharap ini menjadi masalah sama sekali.
sumber
Hanya dengan menggabungkan jawaban teratas, saya menyatukan ekstensi yang sangat sederhana:
Ini bersih, sederhana, dan, oleh komentar @ Jeppe-Stig-Nielsen, cepat.
sumber
where T: Enum
Ada dua cara untuk mengulangi
Enum
:Yang pertama akan memberi Anda nilai dalam bentuk pada array **
object
** s, dan yang kedua akan memberi Anda nilai dalam bentuk array **String
** s.Gunakan dalam satu
foreach
lingkaran seperti di bawah ini:sumber
Saya menggunakan ToString () lalu membaginya dan mem-parsing ludah array di flag.
sumber
Saya tidak berpendapat ini lebih baik, atau bahkan bagus. Saya hanya menyatakan solusi lain.
Jika nilai enum berkisar ketat dari 0 hingga n - 1, alternatif umum adalah:
Jika nilai enum berdekatan dan Anda bisa memberikan elemen pertama dan terakhir dari enum, maka:
Tapi itu tidak sepenuhnya disebutkan, hanya pengulangan. Metode kedua jauh lebih cepat daripada pendekatan lain ...
sumber
Jika Anda membutuhkan pemeriksaan kecepatan dan ketik pada waktu build dan run, metode helper ini lebih baik daripada menggunakan LINQ untuk melemparkan setiap elemen:
Dan Anda bisa menggunakannya seperti di bawah ini:
Tentu saja Anda dapat kembali
IEnumerable<T>
, tetapi itu tidak memberi Anda apa pun di sini.sumber
where T: Enum
Berikut ini adalah contoh kerja membuat opsi pilih untuk DDL :
sumber
(Jawaban yang diterima saat ini memiliki para pemain yang menurut saya tidak diperlukan (walaupun saya mungkin salah).)
sumber
Pertanyaan ini muncul di Bab 10 dari " C # Step by Step 2013 "
Penulis menggunakan double for-loop untuk beralih melalui sepasang Enumerator (untuk membuat setumpuk kartu):
Dalam hal ini,
Suit
danValue
keduanya adalah enumerasi:dan
PlayingCard
merupakan objek kartu dengan yang ditentukanSuit
danValue
:sumber
Saya tahu ini agak berantakan, tetapi jika Anda penggemar one-liners, ini dia:
sumber
Bagaimana jika Anda tahu tipe akan menjadi
enum
, tetapi Anda tidak tahu apa tipe yang tepat pada waktu kompilasi?Metode ini
getListOfEnum
menggunakan refleksi untuk mengambil tipe enum apa pun dan mengembalikanIEnumerable
nilai enum semua.Pemakaian:
sumber
Cara sederhana dan generik untuk mengonversi enum menjadi sesuatu yang dapat Anda berinteraksi:
Lalu:
sumber
Dictionary
bukan ide yang baik: jika Anda memilikiEnum
sukaenum E { A = 0, B = 0 }
, nilai 0 ditambahkan 2 kali menghasilkanArgumentException
(Anda tidak dapat menambahkan yang samaKey
padaDictionary
2 kali atau lebih!).Dictionary<,>
dari metode bernamaToList
? Kenapa tidak kembaliDictionary<T, string>
?Tambahkan metode
public static IEnumerable<T> GetValues<T>()
ke kelas Anda, seperti:Panggil dan berikan enum Anda. Sekarang Anda dapat mengulanginya menggunakan
foreach
:sumber
enum
jenis disebut "jenis enumerasi" bukan karena mereka adalah wadah yang "menyebutkan" nilai (yang bukan), tetapi karena mereka ditentukan dengan menyebutkan nilai yang mungkin untuk variabel jenis itu.(Sebenarnya, itu sedikit lebih rumit dari itu - tipe enum dianggap memiliki tipe integer "mendasar", yang berarti setiap nilai enum sesuai dengan nilai integer (ini biasanya implisit, tetapi dapat ditentukan secara manual). C # dirancang dengan cara sehingga Anda bisa memasukkan bilangan bulat apa pun dari tipe itu ke dalam variabel enum, bahkan jika itu bukan nilai "bernama".)
The Metode System.Enum.GetNames dapat digunakan untuk mengambil array string yang merupakan nama-nama nilai-nilai enum, seperti namanya.
EDIT: Seharusnya menyarankan metode System.Enum.GetValues sebagai gantinya. Ups.
sumber
GetNames
kembali metode, memang, sebuah array string, tapi OP membutuhkan pencacah melalui nilai-nilai.Saya mencoba banyak cara dan mendapatkan hasil dari kode ini:
Untuk mendapatkan daftar int dari enum, gunakan yang berikut ini. Berhasil!
sumber
Anda juga dapat mengikat anggota statis publik enum secara langsung dengan menggunakan refleksi:
sumber
Jika Anda memiliki:
Ini:
Akan menghasilkan:
sumber
Cara Umum LINQ :
Pemakaian:
sumber