Cara menghitung enum


3767

Bagaimana Anda bisa menghitung enumdalam 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 Suitkata kunci, yang kedua.



2
Anda mungkin ingin memeriksa seluk beluk C # enum , yang membahas hal ini serta informasi enum bermanfaat lainnya
ChaseMedallion

Jawaban:


4614
foreach (Suit suit in (Suit[]) Enum.GetValues(typeof(Suit)))
{
}

Catatan : Para pemain untuk (Suit[])tidak sepenuhnya diperlukan, tetapi itu membuat kode 0,5 ns lebih cepat .


97
Ini tidak berfungsi jika Anda memiliki nilai duplikat dalam daftar enumerator.
Jessy

10
Saya hanya ingin menunjukkan bahwa ini, sayangnya tidak akan berfungsi di silverlight, karena perpustakaan silverlight tidak terdiri enum.GetValues. Anda harus menggunakan refleksi dalam hal ini.
Giacomo Tagliabue

146
@Jessy ini tidak bekerja dalam kasus duplikat situasi seperti enum E {A = 0, B = 0}. Enum.GetValuesmenghasilkan dua nilai yang dikembalikan, meskipun mereka sama. E.A == E.Bitu benar, jadi tidak ada perbedaan. Jika Anda ingin nama individual, maka Anda harus mencarinya Enum.GetNames.
nawfal

13
Kemudian jika Anda memiliki duplikat / sinonim dalam enum Anda, dan Anda menginginkan perilaku lainnya, Anda dapat menggunakan Distinctekstensi Linq (sejak .NET 3.5), jadi foreach (var suit in ((Suit[])Enum.GetValues(typeof(Suit))).Distinct()) { }.
Jeppe Stig Nielsen

42
Saya membuat kesalahan dengan mencoba menggunakan varuntuk tipe. Compiler akan membuat variabel Objectbukan enum. Daftar jenis enum secara eksplisit.
jpmc26

695

Bagi saya sepertinya Anda benar-benar ingin mencetak nama masing-masing enum, daripada nilainya. Dalam hal ini Enum.GetNames()tampaknya pendekatan yang tepat.

public enum Suits
{
    Spades,
    Hearts,
    Clubs,
    Diamonds,
    NumSuits
}

public void PrintAllSuits()
{
    foreach (string name in Enum.GetNames(typeof(Suits)))
    {
        System.Console.WriteLine(name);
    }
}

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.

public enum Suits
{
    Spades,
    Hearts,
    Clubs,
    Diamonds,
    NumSuits
}

public void PrintAllSuits()
{
    foreach (var suit in Enum.GetValues(typeof(Suits)))
    {
        System.Console.WriteLine(suit.ToString());
    }
}

2
Sintaks VB di sini: tautan
AndruWitta

Aku mengambil versi dengan perubahan berikut kecil dari sisi saya: Enum.GetValues(typeof(Suits)).OfType<Suits>().ToArray(). Dalam hal ini saya dapat mengulangi array Suitsitem enum, bukan string.
Barabas

@Barabas kenapa tidak lakukan saja Suits suit in Enum.GetValues(typeof(Suits))?
themadking

@memikirkan oh, bung! tentu saja, menggunakan tipe yang tepat terlihat lebih baik daripada kode sh ...
Barabas

337

Saya membuat beberapa ekstensi untuk penggunaan enum yang mudah. Mungkin seseorang bisa menggunakannya ...

public static class EnumExtensions
{
    /// <summary>
    /// Gets all items for an enum value.
    /// </summary>
    /// <typeparam name="T"></typeparam>
    /// <param name="value">The value.</param>
    /// <returns></returns>
    public static IEnumerable<T> GetAllItems<T>(this Enum value)
    {
        foreach (object item in Enum.GetValues(typeof(T)))
        {
            yield return (T)item;
        }
    }

    /// <summary>
    /// Gets all items for an enum type.
    /// </summary>
    /// <typeparam name="T"></typeparam>
    /// <param name="value">The value.</param>
    /// <returns></returns>
    public static IEnumerable<T> GetAllItems<T>() where T : struct
    {
        foreach (object item in Enum.GetValues(typeof(T)))
        {
            yield return (T)item;
        }
    }

    /// <summary>
    /// Gets all combined items from an enum value.
    /// </summary>
    /// <typeparam name="T"></typeparam>
    /// <param name="value">The value.</param>
    /// <returns></returns>
    /// <example>
    /// Displays ValueA and ValueB.
    /// <code>
    /// EnumExample dummy = EnumExample.Combi;
    /// foreach (var item in dummy.GetAllSelectedItems<EnumExample>())
    /// {
    ///    Console.WriteLine(item);
    /// }
    /// </code>
    /// </example>
    public static IEnumerable<T> GetAllSelectedItems<T>(this Enum value)
    {
        int valueAsInt = Convert.ToInt32(value, CultureInfo.InvariantCulture);

        foreach (object item in Enum.GetValues(typeof(T)))
        {
            int itemAsInt = Convert.ToInt32(item, CultureInfo.InvariantCulture);

            if (itemAsInt == (valueAsInt & itemAsInt))
            {
                yield return (T)item;
            }
        }
    }

    /// <summary>
    /// Determines whether the enum value contains a specific value.
    /// </summary>
    /// <param name="value">The value.</param>
    /// <param name="request">The request.</param>
    /// <returns>
    ///     <c>true</c> if value contains the specified value; otherwise, <c>false</c>.
    /// </returns>
    /// <example>
    /// <code>
    /// EnumExample dummy = EnumExample.Combi;
    /// if (dummy.Contains<EnumExample>(EnumExample.ValueA))
    /// {
    ///     Console.WriteLine("dummy contains EnumExample.ValueA");
    /// }
    /// </code>
    /// </example>
    public static bool Contains<T>(this Enum value, T request)
    {
        int valueAsInt = Convert.ToInt32(value, CultureInfo.InvariantCulture);
        int requestAsInt = Convert.ToInt32(request, CultureInfo.InvariantCulture);

        if (requestAsInt == (valueAsInt & requestAsInt))
        {
            return true;
        }

        return false;
    }
}

Enum itu sendiri harus didekorasi dengan FlagsAttribute :

[Flags]
public enum EnumExample
{
    ValueA = 1,
    ValueB = 2,
    ValueC = 4,
    ValueD = 8,
    Combi = ValueA | ValueB
}

13
Satu liner untuk metode ekstensi pertama; tidak lagi malas. return Enum.GetValues ​​(typeof (T)). Cast <T> ();
Leyu

2
Atau Anda dapat menggunakan OfType juga: Enum.GetValues ​​(typeof (T)). OfType <T> (). Sayang sekali tidak ada versi generik dari GetValues ​​<T> () maka itu akan menjadi lebih apik.
jpierson

3
Mungkin seseorang bisa menunjukkan cara menggunakan ekstensi ini? Kompiler tidak menunjukkan metode ekstensi pada enum EnumExample.
Tomas

1
adakah yang bisa menambahkan contoh bagaimana memanfaatkan fungsi-fungsi itu?
Ashwini Verma

3
+1 untuk kode yang dapat digunakan kembali: contoh - simpan metode ekstensi ini di perpustakaan dan rujuk [Bendera] publik ke mytypes {name1, name2}; Daftar <string> myTypeNames = mytypes.GetAllItems ();
Krishna

178

Beberapa versi kerangka .NET tidak mendukung Enum.GetValues. Inilah solusi yang baik dari Ideas 2.0: Enum.GetValues ​​dalam Compact Framework :

public Enum[] GetValues(Enum enumeration)
{
    FieldInfo[] fields = enumeration.GetType().GetFields(BindingFlags.Static | BindingFlags.Public);
    Enum[] enumerations = new Enum[fields.Length];

    for (var i = 0; i < fields.Length; i++)
        enumerations[i] = (Enum) fields[i].GetValue(enumeration);

    return enumerations;
}

Seperti halnya kode apa pun yang melibatkan refleksi , Anda harus mengambil langkah-langkah untuk memastikan itu berjalan hanya sekali dan hasilnya di-cache.


18
Mengapa tidak menggunakan kata kunci hasilkan di sini sebagai ganti daftar?
Eric Mickelsen

1
atau lebih pendek:return type.GetFields().Where(x => x.IsLiteral).Select(x => x.GetValue(null)).Cast<Enum>();
nawfal

7
@nawfal: Linq tidak tersedia. Net CF 2.0.
Gabriel GM

@Ekevoo Bagaimana cara mengikat nilai enum ini ke DropDownList di MVC?
Jack

115

Gunakan Cast<T>:

var suits = Enum.GetValues(typeof(Suit)).Cast<Suit>();

Ini dia IEnumerable<Suit>,.


1
Ini juga berfungsi di fromklausa dan foreachdeklarator header.
Aluan Haddad

97

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 jika Suitbukan enum.

EnumLoop<Suit>.ForEach((suit) => {
    DoSomethingWith(suit);
});

EnumLoop memiliki definisi yang sepenuhnya generik ini:

class EnumLoop<Key> where Key : struct, IConvertible {
    static readonly Key[] arr = (Key[])Enum.GetValues(typeof(Key));
    static internal void ForEach(Action<Key> act) {
        for (int i = 0; i < arr.Length; i++) {
            act(arr[i]);
        }
    }
}

6
Hati-hati menggunakan obat generik seperti ini. Jika Anda mencoba menggunakan EnumLoopdengan beberapa jenis yang bukan enum, ia akan dikompilasi dengan baik, tetapi melemparkan pengecualian saat runtime.
svick

7
Terima kasih svick. Pengecualian runtime sebenarnya akan terjadi dengan jawaban lain di halaman ini ... kecuali yang ini karena saya telah menambahkan "di mana Kunci: struct, IConvertible" sehingga Anda mendapatkan kesalahan waktu kompilasi dalam kebanyakan kasus.
James

3
Tidak, GetValues ​​() dipanggil hanya sekali di foreach.
Alex Blokha

4
James, saya akan mengecilkan kelas Anda karena pandai menulis, tetapi dalam kode produksi yang akan dipelihara dan diperbarui oleh banyak orang, pandai adalah pekerjaan ekstra. Jika itu membuat penghematan besar atau akan banyak digunakan - jadi penghematannya besar dan orang-orang akan mengenalnya - itu sepadan, tetapi dalam kebanyakan kasus memperlambat orang yang mencoba membaca dan memperbarui kode dan memperkenalkan kemungkinan sumber bug di masa depan. Lebih sedikit kode lebih baik :) lebih sedikit kompleksitas bahkan lebih baik.
Grant M

2
@GrantM Kenapa? Kode ini tidak rumit, dan sangat pendek. Selain itu, menulis kelas satu kali akan memungkinkan iterasi kode yang lebih pendek dengan menggunakan sesuai contohnya. Ini sangat bersih, jika Anda tidak dapat memperbarui kode itu, Anda mungkin tidak dapat memperbarui salah satu kode perusahaan.
Dispersia

77

Anda tidak akan mendapatkan Enum.GetValues()di Silverlight .

Posting Blog Asli oleh Einar Ingebrigtsen :

public class EnumHelper
{
    public static T[] GetValues<T>()
    {
        Type enumType = typeof(T);

        if (!enumType.IsEnum)
        {
            throw new ArgumentException("Type '" + enumType.Name + "' is not an enum");
        }

        List<T> values = new List<T>();

        var fields = from field in enumType.GetFields()
                     where field.IsLiteral
                     select field;

        foreach (FieldInfo field in fields)
        {
            object value = field.GetValue(enumType);
            values.Add((T)value);
        }

        return values.ToArray();
    }

    public static object[] GetValues(Type enumType)
    {
        if (!enumType.IsEnum)
        {
            throw new ArgumentException("Type '" + enumType.Name + "' is not an enum");
        }

        List<object> values = new List<object>();

        var fields = from field in enumType.GetFields()
                     where field.IsLiteral
                     select field;

        foreach (FieldInfo field in fields)
        {
            object value = field.GetValue(enumType);
            values.Add(value);
        }

        return values.ToArray();
    }
}

2
Solusi yang bagus, tetapi beberapa refactoring akan lebih baik! :)
nawfal

Saya menggunakan .NET framework 4.0 & silverlight enum.getvalues ​​berfungsi, kode yang saya gunakan adalah ---> enum.GetValues ​​(typeof (enum))
Ananda

2
Dimulai dengan C # 7.3 (Visual Studio 2017 ≥ v15.7), orang dapat menggunakanwhere T: Enum
Yahoo Serious

59

Solusi saya bekerja di .NET Compact Framework (3.5) dan mendukung pengecekan tipe pada waktu kompilasi :

public static List<T> GetEnumValues<T>() where T : new() {
    T valueType = new T();
    return typeof(T).GetFields()
        .Select(fieldInfo => (T)fieldInfo.GetValue(valueType))
        .Distinct()
        .ToList();
}

public static List<String> GetEnumNames<T>() {
    return typeof (T).GetFields()
        .Select(info => info.Name)
        .Distinct()
        .ToList();
}
  • Jika ada yang tahu bagaimana cara menghilangkannya T valueType = new T(), saya akan senang melihat solusinya.

Panggilan akan terlihat seperti ini:

List<MyEnum> result = Utils.GetEnumValues<MyEnum>();

2
bagaimana dengan menggunakan T valueType = default(T)?
Oliver

Hebat, saya bahkan tidak tahu kata kunci itu. Selalu senang mempelajari sesuatu yang baru. Terima kasih! Apakah selalu mengembalikan referensi ke objek yang sama, atau apakah itu membuat instance baru setiap kali pernyataan default dipanggil? Saya belum menemukan sesuatu di internet tentang ini sejauh ini, tetapi jika itu menciptakan contoh baru setiap kali, itu semacam kekalahan tujuan yang saya cari (memiliki satu-baris ^^).
Mallox

1
Bukankah ini akan menciptakan contoh baru untuk setiap iterasi selama enumerasi?
Mallox

1
-1 untuk "mendukung pengecekan tipe pada waktu kompilasi:". Memeriksa jenis apa? Ini akan berhasil untuk apa pun new() T. Juga, Anda tidak perlu new T()sama sekali, Anda dapat memilih hanya bidang statis saja dan lakukan .GetValue(null). Lihat jawaban Aubrey.
nawfal

2
Dimulai dengan C # 7.3 (Visual Studio 2017 ≥ v15.7), orang dapat menggunakanwhere T: Enum
Yahoo Serious


50
public void PrintAllSuits()
{
    foreach(string suit in Enum.GetNames(typeof(Suits)))
    {
        Console.WriteLine(suit);
    }
}

2
Itu menghitung string, jangan lupa untuk mengubah hal-hal itu kembali ke nilai enumerasi sehingga enumerasi dapat disebutkan.
Ian Boyd

1
Saya melihat dari hasil edit Anda bahwa Anda ingin benar-benar beroperasi pada enum itu sendiri, kode di atas ditujukan pada posting asli Anda.
Joshua Drake

49
foreach (Suit suit in Enum.GetValues(typeof(Suit))) { }

Saya pernah mendengar desas-desus yang tidak jelas bahwa ini sangat lambat. Adakah yang tahu - Orion Edwards 15 Okt08 pada 1:31 7

Saya pikir caching array akan mempercepatnya. Sepertinya Anda mendapatkan array baru (melalui refleksi) setiap saat. Agak:

Array enums = Enum.GetValues(typeof(Suit));
foreach (Suit suitEnum in enums) 
{
    DoSomething(suitEnum);
}

Setidaknya itu sedikit lebih cepat, ja?


5
Kompiler harus menangani ini.
Stephan Bijzitter

@StephanBijzitter Wow, Anda membaca yang jauh di bawah ini :-) Saya setuju, kompiler harus membuat solusi saya tidak perlu.
Penebusan Terbatas

1
Ini tidak perlu. Melihat kode yang dikompilasi di ILSpy, kompiler pasti sudah melakukan ini. Mengapa jawaban ini dijatuhkan sama sekali, apalagi 35 kali?
mhenry1384

1
Sudah diputuskan sejak lama. Dulu sekali. Saya akan bertaruh bahwa kompiler akan memecahkan ini saat itu juga. Tapi itu benar-benar terlihat lebih performant, bukan? ;-)
Kurban Tebusan Terbatas

32

Tiga jalan:

  1. Enum.GetValues(type) // Sejak. NET 1.1, bukan di Silverlight atau .NET Compact Framework
  2. type.GetEnumValues() // Hanya di .NET 4 dan di atasnya
  3. type.GetFields().Where(x => x.IsLiteral).Select(x => x.GetValue(null)) // Bekerja di mana-mana

Saya tidak yakin mengapa GetEnumValuesdiperkenalkan 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:

public static class Enum<T> where T : struct, IComparable, IFormattable, IConvertible
{
    public static IEnumerable<T> GetValues()
    {
        return (T[])Enum.GetValues(typeof(T));
    }

    public static IEnumerable<string> GetNames()
    {
        return Enum.GetNames(typeof(T));
    }
}

Sekarang Anda menelepon:

Enum<Suit>.GetValues();

// Or
Enum.GetValues(typeof(Suit)); // Pretty consistent style

Seseorang juga dapat menggunakan semacam caching jika masalah kinerja, tapi saya tidak berharap ini menjadi masalah sama sekali.

public static class Enum<T> where T : struct, IComparable, IFormattable, IConvertible
{
    // Lazily loaded
    static T[] values;
    static string[] names;

    public static IEnumerable<T> GetValues()
    {
        return values ?? (values = (T[])Enum.GetValues(typeof(T)));
    }

    public static IEnumerable<string> GetNames()
    {
        return names ?? (names = Enum.GetNames(typeof(T)));
    }
}

Ini adalah ringkasan metode yang bagus. Saya pikir Anda harus menggabungkan jawaban Anda yang lain ke dalam ini. Yang benar adalah bahwa enum adalah istimewa dan berulang kali (biasanya) sama validnya dengan enumerasi karena Anda tahu bahwa nilainya tidak akan pernah berubah. TKI, jika Anda memiliki enum yang berubah sepanjang waktu, maka Anda telah memilih konstruk data yang salah.
krowe2

31

Hanya dengan menggabungkan jawaban teratas, saya menyatukan ekstensi yang sangat sederhana:

public static class EnumExtensions
{
    /// <summary>
    /// Gets all items for an enum value.
    /// </summary>
    /// <typeparam name="T"></typeparam>
    /// <param name="value">The value.</param>
    /// <returns></returns>
    public static IEnumerable<T> GetAllItems<T>(this T value) where T : Enum
    {
        return (T[])Enum.GetValues(typeof (T));
    }
}

Ini bersih, sederhana, dan, oleh komentar @ Jeppe-Stig-Nielsen, cepat.


6
Dimulai dengan C # 7.3 (Visual Studio 2017 ≥ v15.7), orang dapat menggunakanwhere T: Enum
Yahoo Serious

24

Ada dua cara untuk mengulangi Enum:

1. var values =  Enum.GetValues(typeof(myenum))
2. var values =  Enum.GetNames(typeof(myenum))

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 foreachlingkaran seperti di bawah ini:

foreach(var value in values)
{
    // Do operations here
}

2
Mungkin karena ini sudah tercakup dalam banyak jawaban? Jangan membuat jawaban berlebihan.
nawfal

@nawfal ya mungkin tercakup dalam jawaban lain, meskipun tidak disimpulkan dengan baik di sebagian besar dari mereka.
Kylo Ren

23

Saya menggunakan ToString () lalu membaginya dan mem-parsing ludah array di flag.

[Flags]
public enum ABC {
   a = 1,
   b = 2,
   c = 4
};

public IEnumerable<ABC> Getselected (ABC flags)
{
   var values = flags.ToString().Split(',');
   var enums = values.Select(x => (ABC)Enum.Parse(typeof(ABC), x.Trim()));
   return enums;
}

ABC temp= ABC.a | ABC.b;
var list = getSelected (temp);
foreach (var item in list)
{
   Console.WriteLine(item.ToString() + " ID=" + (int)item);
}

17

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:

public void EnumerateEnum<T>()
{
    int length = Enum.GetValues(typeof(T)).Length;
    for (var i = 0; i < length; i++)
    {
        var @enum = (T)(object)i;
    }
}

Jika nilai enum berdekatan dan Anda bisa memberikan elemen pertama dan terakhir dari enum, maka:

public void EnumerateEnum()
{
    for (var i = Suit.Spade; i <= Suit.Diamond; i++)
    {
        var @enum = i;
    }
}

Tapi itu tidak sepenuhnya disebutkan, hanya pengulangan. Metode kedua jauh lebih cepat daripada pendekatan lain ...


16

Jika Anda membutuhkan pemeriksaan kecepatan dan ketik pada waktu build dan run, metode helper ini lebih baik daripada menggunakan LINQ untuk melemparkan setiap elemen:

public static T[] GetEnumValues<T>() where T : struct, IComparable, IFormattable, IConvertible
{
    if (typeof(T).BaseType != typeof(Enum))
    {
        throw new ArgumentException(string.Format("{0} is not of type System.Enum", typeof(T)));
    }
    return Enum.GetValues(typeof(T)) as T[];
}

Dan Anda bisa menggunakannya seperti di bawah ini:

static readonly YourEnum[] _values = GetEnumValues<YourEnum>();

Tentu saja Anda dapat kembali IEnumerable<T>, tetapi itu tidak memberi Anda apa pun di sini.


3
Dimulai dengan C # 7.3 (Visual Studio 2017 ≥ v15.7), orang dapat menggunakanwhere T: Enum
Yahoo Serious

14

Berikut ini adalah contoh kerja membuat opsi pilih untuk DDL :

var resman = ViewModelResources.TimeFrame.ResourceManager;

ViewBag.TimeFrames = from MapOverlayTimeFrames timeFrame
      in Enum.GetValues(typeof(MapOverlayTimeFrames))
      select new SelectListItem
      {
         Value = timeFrame.ToString(),
         Text = resman.GetString(timeFrame.ToString()) ?? timeFrame.ToString()
      };

10
foreach (Suit suit in Enum.GetValues(typeof(Suit)))
{
}

(Jawaban yang diterima saat ini memiliki para pemain yang menurut saya tidak diperlukan (walaupun saya mungkin salah).)


10

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):

class Pack
{
    public const int NumSuits = 4;
    public const int CardsPerSuit = 13;
    private PlayingCard[,] cardPack;

    public Pack()
    {
        this.cardPack = new PlayingCard[NumSuits, CardsPerSuit];
        for (Suit suit = Suit.Clubs; suit <= Suit.Spades; suit++)
        {
            for (Value value = Value.Two; value <= Value.Ace; value++)
            {
                cardPack[(int)suit, (int)value] = new PlayingCard(suit, value);
            }
        }
    }
}

Dalam hal ini, Suitdan Valuekeduanya adalah enumerasi:

enum Suit { Clubs, Diamonds, Hearts, Spades }
enum Value { Two, Three, Four, Five, Six, Seven, Eight, Nine, Ten, Jack, Queen, King, Ace}

dan PlayingCardmerupakan objek kartu dengan yang ditentukan Suitdan Value:

class PlayingCard
{
    private readonly Suit suit;
    private readonly Value value;

    public PlayingCard(Suit s, Value v)
    {
        this.suit = s;
        this.value = v;
    }
}

apakah ini akan bekerja jika nilai-nilai dalam enum tidak berurutan?
Aamir Masood


8

Bagaimana jika Anda tahu tipe akan menjadi enum, tetapi Anda tidak tahu apa tipe yang tepat pada waktu kompilasi?

public class EnumHelper
{
    public static IEnumerable<T> GetValues<T>()
    {
        return Enum.GetValues(typeof(T)).Cast<T>();
    }

    public static IEnumerable getListOfEnum(Type type)
    {
        MethodInfo getValuesMethod = typeof(EnumHelper).GetMethod("GetValues").MakeGenericMethod(type);
        return (IEnumerable)getValuesMethod.Invoke(null, null);
    }
}

Metode ini getListOfEnummenggunakan refleksi untuk mengambil tipe enum apa pun dan mengembalikan IEnumerablenilai enum semua.

Pemakaian:

Type myType = someEnumValue.GetType();

IEnumerable resultEnumerable = getListOfEnum(myType);

foreach (var item in resultEnumerable)
{
    Console.WriteLine(String.Format("Item: {0} Value: {1}",item.ToString(),(int)item));
}

8

Cara sederhana dan generik untuk mengonversi enum menjadi sesuatu yang dapat Anda berinteraksi:

public static Dictionary<int, string> ToList<T>() where T : struct
{
   return ((IEnumerable<T>)Enum
       .GetValues(typeof(T)))
       .ToDictionary(
           item => Convert.ToInt32(item),
           item => item.ToString());
}

Lalu:

var enums = EnumHelper.ToList<MyEnum>();

A Dictionarybukan ide yang baik: jika Anda memiliki Enumsuka enum E { A = 0, B = 0 }, nilai 0 ditambahkan 2 kali menghasilkan ArgumentException(Anda tidak dapat menambahkan yang sama Keypada Dictionary2 kali atau lebih!).
Massimiliano Kraus

Mengapa mengembalikan a Dictionary<,>dari metode bernama ToList? Kenapa tidak kembali Dictionary<T, string>?
Aluan Haddad

8

Tambahkan metode public static IEnumerable<T> GetValues<T>()ke kelas Anda, seperti:

public static IEnumerable<T> GetValues<T>()
{
    return Enum.GetValues(typeof(T)).Cast<T>();
}

Panggil dan berikan enum Anda. Sekarang Anda dapat mengulanginya menggunakan foreach:

 public static void EnumerateAllSuitsDemoMethod()
 {
     // Custom method
     var foos = GetValues<Suit>();
     foreach (var foo in foos)
     {
         // Do something
     }
 }

2

enumjenis 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.


2
Meskipun jawaban Anda benar, jawabannya tidak benar-benar menjawab pertanyaan awal OP. The GetNameskembali metode, memang, sebuah array string, tapi OP membutuhkan pencacah melalui nilai-nilai.
Silviu Preda

@ SilviuPreda: Diedit. Seharusnya GetValues ​​bukan GetNames.
Emily Chen

2

Saya mencoba banyak cara dan mendapatkan hasil dari kode ini:

Untuk mendapatkan daftar int dari enum, gunakan yang berikut ini. Berhasil!

List<int> listEnumValues = new List<int>();
YourEnumType[] myEnumMembers = (YourEnumType[])Enum.GetValues(typeof(YourEnumType));
foreach ( YourEnumType enumMember in myEnumMembers)
{
    listEnumValues.Add(enumMember.GetHashCode());
}

1
tanx untuk edit @ peter-mortensen
reza akhlaghi

0

Anda juga dapat mengikat anggota statis publik enum secara langsung dengan menggunakan refleksi:

typeof(Suit).GetMembers(BindingFlags.Public | BindingFlags.Static)
    .ToList().ForEach(x => DoSomething(x.Name));

0

Jika Anda memiliki:

enum Suit
{
   Spades,
   Hearts,
   Clubs,
   Diamonds
}

Ini:

foreach (var e in Enum.GetValues(typeof(Suit)))
{
    Console.WriteLine(e.ToString() + " = " + (int)e);
}

Akan menghasilkan:

Spades = 0
Hearts = 1
Clubs = 2
Diamonds = 3

0

Cara Umum LINQ :

    public static Dictionary<int, string> ToList<T>() where T : struct =>
        ((IEnumerable<T>)Enum.GetValues(typeof(T))).ToDictionary(value => Convert.ToInt32(value), value => value.ToString());

Pemakaian:

        var enums = ToList<Enum>();
Dengan menggunakan situs kami, Anda mengakui telah membaca dan memahami Kebijakan Cookie dan Kebijakan Privasi kami.
Licensed under cc by-sa 3.0 with attribution required.