Bir numaralandırma nasıl numaralandırılır


3766

Nasıl bir enumC # numaralandırmak ?

Örneğin, aşağıdaki kod derlenmez:

public enum Suit
{
    Spades,
    Hearts,
    Clubs,
    Diamonds
}

public void EnumerateAllSuitsDemoMethod()
{
    foreach (Suit suit in Suit)
    {
        DoSomething(suit);
    }
}

Ve aşağıdaki derleme zamanı hatası verir:

'Suit' bir 'tiptir' ancak 'değişken' gibi kullanılır

Suitİkincisi , anahtar kelimede başarısız olur .



2
Bunu ve diğer yararlı numaralandırma
tidbitlerini

Yanıtlar:


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

Not : Döküm işlemi (Suit[])kesinlikle gerekli değildir, ancak kodu 0,5 ns daha hızlı yapar .


97
Numaralandırıcı listesinde yinelenen değerler varsa bu çalışmaz.
Jessy

10
Sadece şunu belirtmek istiyorum, maalesef silverlight'ta çalışmaz, silverlight kütüphanesi içermez enum.GetValues. Bu durumda yansımayı kullanmalısınız.
Giacomo Tagliabue

146
Bu @Jessy yaptığı gibi yinelenen durumlar halinde çalışmalarını enum E {A = 0, B = 0}. Enum.GetValuesaynı olmalarına rağmen iki değer döndürülür. E.A == E.Bdoğrudur, bu yüzden bir ayrım yoktur. Bireysel isimler istiyorsanız, aramalısınız Enum.GetNames.
nawfal

13
Sonra numaralandırma yinelenen / eş anlamlı varsa ve diğer davranış istiyorsanız, Linq Distinctuzantısını (.NET 3.5 beri) kullanabilirsiniz foreach (var suit in ((Suit[])Enum.GetValues(typeof(Suit))).Distinct()) { }.
Jeppe Stig Nielsen

42
varTip için kullanmaya çalışırken hata yaptım . Derleyici değişkeni Objectenum yerine bir yapar . Numaralandırma türünü açıkça listeleyin.
jpmc26

695

Bana, değerlerden ziyade her bir numaralandırmanın adını yazdırmak istediğiniz gibi görünüyor. Bu durumda Enum.GetNames()doğru yaklaşım gibi görünüyor.

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

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

Bu arada, değeri artırmak, bir numaralandırmanın değerlerini numaralandırmak için iyi bir yol değildir. Bunun yerine bunu yapmalısınız.

Onun Enum.GetValues(typeof(Suit))yerine kullanırdım.

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
VB Sözdizimi burada: bağlantı
AndruWitta

Yanımda küçük bir şu değişikliklerle sürümüne aldı: Enum.GetValues(typeof(Suits)).OfType<Suits>().ToArray(). Bu durumda Suitsdizeleri değil , numaralandırma öğelerinin dizisini yineleyebilirim .
Barabas

@Barabas neden sadece yapmıyorsunuz Suits suit in Enum.GetValues(typeof(Suits))?
themadking

@ themadking oh, adamım! Tabii ki, tam türü kullanmak bu korkunç sh ... kod parçasından daha iyi görünüyor !
Barabas

337

Kolay numaralandırma kullanımı için bazı uzantılar yaptım. Belki birisi kullanabilir ...

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;
    }
}

Numaralandırmanın kendisi FlagsAttribute ile dekore edilmelidir :

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

13
İlk genişletme yöntemi için bir astar; artık tembel değil. return Enum.GetValues ​​(typeof (T)). Cast <T> ();
Leyu

2
Alternatif olarak OfType'ı da kullanabilirsiniz: Enum.GetValues ​​(typeof (T)) .Tip <T> (). GetValues ​​<T> () 'in genel bir sürümü olmadığında çok kötü, o zaman daha da kaygan olur.
jpierson

3
Belki birisi bu uzantıları nasıl kullanacağını gösterebilir? Derleyici, EnumExample enum üzerinde uzantı yöntemleri göstermez.
Tomas

1
Herkes nasıl bu işlevleri kullanmak için örnek ekleyebilir?
Ashwini Verma

3
Yeniden kullanılabilir kod için +1: örnekler - bu uzantı yöntemlerini bir kitaplığa kaydedin ve ona [Flags] public enum mytypes {name1, name2}; List <string> myTypeNames = mytypes.GetAllItems ();
Krishna

178

.NET çerçevesinin bazı sürümleri desteklenmez Enum.GetValues. Aşağıda , Compact 2.0'daki Fikirler 2.0: Enum.GetValues'dan iyi bir çözüm bulunmaktadır :

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;
}

Yansıma içeren herhangi bir kodda olduğu gibi, kodun yalnızca bir kez çalıştığından ve sonuçların önbelleğe alındığından emin olmak için adımlar atmalısınız.


18
Neden bir liste somutlaştırmak yerine verim anahtar kelimesini kullanmıyorsunuz?
Eric Mickelsen

1
veya daha kısa:return type.GetFields().Where(x => x.IsLiteral).Select(x => x.GetValue(null)).Cast<Enum>();
nawfal

7
@nawfal: Linq kullanılamıyor. Net CF 2.0.
Gabriel GM

@Ekevoo Bu numaralandırma değerleri MVC bir DropDownList'e nasıl bağlanır?
Jack,

115

Kullanım Cast<T>:

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

İşte böyle IEnumerable<Suit>.


1
Bu, fromyan tümcede ve foreachbaşlık beyanında da çalışır .
Aluan Haddad

97

Ben GetValues()her döngü olduğunda çağrılmaz çünkü bu diğer öneriler daha verimli olduğunu düşünüyorum . Aynı zamanda daha özlü. Ve bir derleme zamanı hatası alırsınız, eğer değilse bir çalışma zamanı istisnası Suitdeğil enum.

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

EnumLoop tamamen genel bir tanımı var:

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
Bunun gibi jenerik ilaçları kullanmaya dikkat edin. Bir EnumLoopnumaralandırma olmayan bir türle kullanmaya çalışırsanız , iyi derlenir, ancak çalışma zamanında bir istisna atar.
svick

7
Teşekkürler svick. Çalışma zamanı istisnaları aslında bu sayfadaki diğer cevaplarla ortaya çıkacaktır ... bunun dışında, çoğu durumda derleme zamanı hatası almanız için "nerede Key: struct, IConvertible" ekledim.
James

3
Hayır, GetValues ​​() foreach içinde yalnızca bir kez çağrılır.
Alex Blokha

4
James, zeki yazmak güzel, ama üretim kodunda birçok insanın koruyacağı ve güncelleyeceği için sınıfını caydırırdım, zeki ekstra iş. Büyük bir tasarruf sağlıyorsa veya çok kullanılacaksa - tasarruflar büyük ve insanlar buna aşina olacaksa - buna değer, ancak çoğu durumda kodu okumaya ve güncellemeye çalışan insanları yavaşlatır ve olası bir gelecekte kaynak hataları. Daha az kod daha iyidir :) daha az karmaşıklık daha da iyidir.
Grant M

2
@GrantM Neden? Bu kod da karmaşık değildir ve inanılmaz derecede kısadır. Bunun da ötesinde, sınıfın bir kez yazılması, kod kullanımıyla daha kısa yinelemelere izin verecektir. Bu son derece temiz, bu kodu güncelleyemiyorsanız, büyük olasılıkla hiçbir şirket kodunu güncelleyemezsiniz.
Dispersia

77

Sen almazsınız Enum.GetValues()içinde Silverlight .

Einar Ingebrigtsen tarafından yazılan blog yazısı :

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
Güzel bir çözüm, ancak bazı yeniden düzenleme daha iyi olacak! :)
nawfal

.NET framework 4.0 ve silverlight enum.getvalues ​​çalışmasını kullanıyorum, kullandığım kod ---> enum.GetValues ​​(typeof (enum))
Ananda

2
C # 7.3 ile başlayan (Visual Studio 2017 ≥ v15.7), biri kullanılabilirwhere T: Enum
Yahoo Serious

59

Çözümüm .NET Compact Framework'te (3.5) çalışır ve derleme zamanında tür denetimini destekler :

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();
}
  • Eğer kimse ondan nasıl kurtulacağını bilirse T valueType = new T(), bir çözüm gördüğüme sevinirim.

Bir çağrı şöyle görünecektir:

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

2
kullanmaya ne dersin T valueType = default(T)?
Oliver

Harika, o anahtar kelimeyi bile bilmiyordum. Her zaman yeni bir şeyler öğrenmek güzel. Teşekkür ederim! Her zaman aynı nesneye başvuru döndürüyor mu yoksa varsayılan deyim her çağrıldığında yeni bir örnek mi oluşturuyor? Şimdiye kadar bu konuda net bir şey bulamadım, ancak her seferinde yeni bir örnek oluşturuyorsa, aradığım amacı yener (bir astarlı ^ ^).
Mallox

1
Bu, numaralandırma üzerindeki her yineleme için yeni bir örnek oluşturmaz mı?
Mallox

1
-1 için "derleme zamanında tür denetimini destekler:". Ne tür kontrol? Bu herhangi biri için işe yarar new() T. Ayrıca, new T()hiç ihtiyacınız yok , sadece statik alanları tek başına seçebilir ve yapabilirsiniz .GetValue(null). Aubrey'nin cevabına bakın.
nawfal

2
C # 7.3 ile başlayan (Visual Studio 2017 ≥ v15.7), biri kullanılabilirwhere T: Enum
Yahoo Serious


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

2
Bu bir dize numaralandırır, bu numaralandırmayı numaralandırmak için bunları bir numaralandırma değerine dönüştürmeyi unutmayın.
Ian Boyd

1
Düzenlemenizden, numaralandırmaların kendisinde gerçekten işlemek istediğinizi görüyorum, yukarıdaki kod orijinal yayınınızı ele aldı.
Joshua Drake

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

Bunun terifik olarak yavaş olduğuna dair belirsiz söylentiler duydum. Kimse biliyor mu? - Orion Edwards 15 Ekim 08:31 7

Ben dizi önbellekleme önemli ölçüde hızlandıracağını düşünüyorum. Her seferinde yeni bir dizi (yansıma yoluyla) alıyorsunuz gibi görünüyor. Daha doğrusu:

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

Bu en azından biraz daha hızlı, değil mi?


5
Derleyici bununla ilgilenmelidir.
Stephan Bijzitter

@StephanBijzitter Wow, bu konuda oldukça aşağı okuyorsunuz :-) Katılıyorum, derleyici benim çözümümüzü gereksiz hale getirmeli.
Sınırlı Kefaret

1
Bu gerekli değil. ILSpy'daki derlenmiş koda baktığımızda, derleyici kesinlikle bunu zaten yapıyor. Bu cevap neden 35 kat daha az değerlendirildi?
mhenry1384

1
Uzun zaman önce iptal edildi. Çok uzun zaman önce. Derleyicinin bunu o zamana kadar çözeceğini iddia ediyorum. Ama kesinlikle daha performanslı görünüyor , değil mi? ;-)
Sınırlı Kefaret

32

Üç yol:

  1. Enum.GetValues(type) // .NET 1.1'den beri Silverlight veya .NET Compact Framework'te değil
  2. type.GetEnumValues() // Yalnızca .NET 4 ve üstü sürümlerde
  3. type.GetFields().Where(x => x.IsLiteral).Select(x => x.GetValue(null)) // Her yerde çalışır

GetEnumValuesTip örneklerinde neden tanıtıldığından emin değilim . Benim için hiç okunabilir değil.


Enum<T>Benim için en okunaklı ve unutulmaz olanı gibi yardımcı bir sınıfa sahip olmak :

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));
    }
}

Şimdi ara:

Enum<Suit>.GetValues();

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

Performans önemliyse bir tür önbellekleme de kullanılabilir, ancak bunun bir sorun olmasını beklemiyorum.

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)));
    }
}

Bu yöntemlerin güzel bir özeti. Sanırım diğer cevabınızı bu konuyla birleştirmelisiniz. Gerçek şu ki, enum özeldir ve bunlar arasında döngü yapmak genellikle (genellikle) numaralandırma kadar geçerlidir çünkü değerlerin asla değişmeyeceğini bilirsiniz. IOW, Sürekli değişen bir enumunuz varsa, başlamak için yanlış veri yapısını seçtiniz.
krowe2

31

Sadece en iyi cevapları birleştirerek, çok basit bir uzantıyı bir araya getirdim:

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));
    }
}

Temiz, basit ve @ Jeppe-Stig-Nielsen'in yorumuna göre hızlı.


6
C # 7.3 ile başlayan (Visual Studio 2017 ≥ v15.7), biri kullanılabilirwhere T: Enum
Yahoo Serious

24

Bir yinelemenin iki yolu vardır Enum:

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

Birincisi size ** object** s dizisi biçiminde değerler verir, ikincisi ise ** String** s dizisi biçiminde değerler verir .

foreachAşağıdaki gibi bir döngüde kullanın :

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

2
Belki de bu zaten birçok cevabı kapsıyor? Cevapları gereksiz yapalım.
nawfal

@nawfal evet diğer cevaplarda da yer alabilir, ancak çoğunda iyi sonuçlandırılmamıştır.
Kylo Ren

23

ToString () kullanın sonra bölmek ve tükürük dizisi bayraklar halinde ayrıştırmak.

[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

Bunun daha iyi, hatta daha iyi olduğu görüşüne sahip değilim. Sadece bir çözüm daha söylüyorum.

Enum değerleri kesinlikle 0 ila n - 1 arasındaysa, genel bir alternatif:

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

Numaralandırma değerleri bitişikse ve numaralandırmanın ilk ve son öğesini sağlayabiliyorsanız, o zaman:

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

Ama bu kesinlikle numaralandırıcı değil, sadece döngü. İkinci yöntem, diğer yaklaşımlardan çok daha hızlı ...


16

Derleme ve çalıştırma zamanında hız ve tür denetimine ihtiyacınız varsa, bu yardımcı yöntem her öğeyi yayınlamak için LINQ kullanmaktan daha iyidir:

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[];
}

Ve aşağıdaki gibi kullanabilirsiniz:

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

Tabii ki geri dönebilirsiniz IEnumerable<T>, ama bu size burada hiçbir şey satın almıyor.


3
C # 7.3 ile başlayan (Visual Studio 2017 ≥ v15.7), biri kullanılabilirwhere T: Enum
Yahoo Serious

14

Aşağıda, bir DDL için seçim seçenekleri oluşturmanın çalışan bir örneği verilmiştir :

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)))
{
}

(Şu anda kabul edilen cevabın gerekli olduğunu düşünmediğim bir oyuncu kadrosu var (her ne kadar yanlış olabilirim).)


10

Bu soru " C # Adım Adım 2013 " , Bölüm 10'da görünür

Yazar, bir çift Enumerator ile yineleme yapmak için çift bir for-loop kullanır (tam bir kart destesi oluşturmak için):

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);
            }
        }
    }
}

Bu durumda Suitve Valueher ikisi de numaralandırmadır:

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

ve PlayingCardtanımlanmış olan bir kart amacı Suitve Value:

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

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

enum'daki değerler sıralı değilse bu işe yarar mı?
Aamir Masood


8

Türün bir olacağını biliyor enum, ancak derleme zamanında tam türün ne olduğunu bilmiyorsanız ne olacak?

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);
    }
}

Yöntem getListOfEnum, herhangi bir enum türünü almak için yansıma kullanır ve IEnumerabletüm enum değerlerinden birini döndürür .

Kullanımı:

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

Bir numaralandırmayı etkileşimde bulunabileceğiniz bir şeye dönüştürmenin basit ve genel bir yolu:

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());
}

Ve sonra:

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

A Dictionaryiyi bir fikir değildir: Eğer bir Enumbenzeriniz varsa enum E { A = 0, B = 0 }, 0 değeri bir 2 (bir veya daha fazla kez ArgumentExceptionekleyemezsiniz !) Oluşturarak 2 kez eklenir . KeyDictionary
Massimiliano Kraus

Neden Dictionary<,>adlı bir yöntemden bir döndürür ToList? Ayrıca neden geri dönmeyelim Dictionary<T, string>?
Aluan Haddad

8

public static IEnumerable<T> GetValues<T>()Sınıfınıza aşağıdaki gibi bir yöntem ekleyin :

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

Numaralandırın. Şimdi kullanarak tekrarlayabilirsiniz foreach:

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

2

enumtürlere "numaralandırma türleri" denir, çünkü bunlar değerleri "numaralandıran" kapsayıcılar değildirler (değiller), ancak bu türdeki bir değişken için olası değerler numaralandırılarak tanımlanırlar .

(Aslında, bundan biraz daha karmaşıktır - enum türlerinin "temel" bir tamsayı türüne sahip olduğu düşünülür, bu da her bir enum değerinin bir tamsayı değerine karşılık geldiği anlamına gelir (bu genellikle örtüktür, ancak manuel olarak belirtilebilir). Eğer malzeme diye bir biçimde herhangi bir "adında" değeri olmasa bile, enum değişkenine bu tür tamsayı.)

System.Enum.GetNames yöntemi adından da anlaşılacağı gibi, numaralandırma değerleri isimler şeritlerinin bir dizi almak için kullanılabilir.

EDIT: Bunun yerine System.Enum.GetValues yöntemini önermiş olmalıydı . Hata.


2
Cevabınız kendi içinde doğru olsa da, OP'nin orijinal sorusuna gerçekten değinmiyor. GetNamesYöntem geri döndüğünde, gerçekten de, bir şerit dizisi, fakat OP değerler arasında bir sýralayýcý gerektirir.
Silviu Preda

@SilviuPreda: Düzenlendi. GetNames yerine GetValues ​​olmalıdır.
Emily Chen

2

Birçok yol denedim ve bu koddan sonuç aldım:

Bir numaradan int listesi almak için aşağıdakileri kullanın. İşe yarıyor!

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

1
tanx for edit @ peter-mortensen
reza akhlaghi

0

Ayrıca, yansımayı kullanarak numaralandırmanın genel statik üyelerine doğrudan bağlanabilirsiniz:

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

0

Eğer varsa:

enum Suit
{
   Spades,
   Hearts,
   Clubs,
   Diamonds
}

Bu:

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

Çıktı olacak:

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

0

LINQ Genel Yolu:

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

Kullanımı:

        var enums = ToList<Enum>();
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.