it-swarm-tr.com

C # 'da bir numaralandırmayı nasıl numaralandırırım?

C # içinde bir enum nasıl numaralandırılabilir?

Ö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ı veriyor:

'Takım' bir 'türdür' ancak 'değişken' gibi kullanılır

İkincisi Suit anahtar sözcüğünde başarısız olur.

3435
Ian Boyd
foreach (Suit suit in (Suit[]) Enum.GetValues(typeof(Suit)))
{
}

Not : (Suit[]) öğesine basmak kesinlikle gerekli değildir, ancak 0,5 ns kodunu daha hızlı yapar.

4232
jop

Bana göre, her bir enumun ismini, değerler yerine gerçekten basmak istiyormuşsun gibi geliyor. 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ğerin artırılması bir enum değerlerini saymak için iyi bir yol değildir. Bunun yerine bunu yapmalısın.

Bunun yerine Enum.GetValues(typeof(Suit)) işlevini 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());
    }
}
624
Haacked

Enum kullanımı için bazı eklentiler 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;
    }
}

Enum'un kendisi, FlagsAttribute ile dekore edilmelidir.

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

.NET çerçevesinin bazı sürümleri Enum.GetValues öğesini desteklemez. İşte Ideas 2.0'dan gelen en iyi çözüm: Kompakt Çerçevede Enum.GetValues ​​ :

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

reflection içeren herhangi bir kodda olduğu gibi, yalnızca bir kez çalışmasını ve sonuçların önbelleğe alınmasını sağlamak için adımlar atmanız gerekir.

165
Ekevoo

Neden kimse Cast<T> kullanmıyor?

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

İşte orada IEnumerable<Suit>.

97
sircodesalot

Bunun diğer önerilere göre daha etkili olduğunu düşünüyorum çünkü bir döngü elde ettiğinizde GetValues() çağrılmaz. Aynı zamanda daha özlü. Ve eğer Suit bir enum değilse, bir çalışma zamanı istisnası değil derleme zamanı hatası alırsınız.

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

EnumLoop bu tamamen genel tanımı vardır:

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]);
        }
    }
}
90
James

Silverlight'ta Enum.GetValues() işlevini alamazsınız.

Einar Ingebrigtsen'in Orijinal 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();
    }
}
72
Aubrey Taylor

Sadece kompakt çerçevede (3.5) çalışan ve derleme zamanında türünü kontrol eden çözümümü eklemek için :

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

- T valueType = new T() dosyasından nasıl kurtulacağınızı bilen biri varsa, bir çözüm görmekten mutlu olurum.

Bir arama şuna benzer:

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

Bence kullanabilirsin

Enum.GetNames(Suit)
48
Tom Carr
public void PrintAllSuits()
{
    foreach(string suit in Enum.GetNames(typeof(Suits)))
    {
        Console.WriteLine(suit);
    }
}
46
Joshua Drake
foreach (Suit suit in Enum.GetValues(typeof(Suit))) { }

Belirsizce yavaş olduğuna dair belirsiz söylentiler duydum. Bilen var mı? - Orion Edwards 15 Ekim '01: 31'de 7

Diziyi önbelleğe almanın çok fazla hızlanacağı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ı, ja?

44

Üç yol:

1. Enum.GetValues(type) //since .NET 1.1, not in silverlight or compact framewok
2. type.GetEnumValues() //only on .NET 4 and above
3. type.GetFields().Where(x => x.IsLiteral).Select(x => x.GetValue(null)) //works everywhere

Tip örneği üzerine neden GetEnumValues tanıtıldığından emin değilim, bu benim için hiç okunamıyor.


Enum<T> gibi yardımcı bir sınıfa sahip olmak benim için en okunaklı ve akılda kalıcı olan şeydir:

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

Biri, performans önemliyse, bir tür önbellek de kullanabilir, 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)));
    }
}
25
nawfal

Ne cehenneme fırlatıp atacağım, sadece en iyi cevapları bir araya getirerek çok basit bir uzantısı

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 yorumuyla hızlı.

22
Darkside

ToString () kullanıp sonra spit dizisini bayraklar halinde bölüp ayrıştırıyorum.

[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);
}
21
Mickey Perlstein

Enum öğesini yinelemenin iki yolu vardır:

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

Birincisi,objectdizisindeki formları verir ve ikincisi sizeStringdizisi biçimindeki değerleri verir.

Aşağıdaki gibi foreach döngüsünde kullanın:

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

Derleme ve çalıştırma zamanında hız ve tür kontrolü gerekiyorsa, 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 IEnumerable<T> 'a dönebilirsiniz, ancak bu size burada hiçbir şey satın almaz.

15
dmihailescu

Bunun daha iyi, hatta daha iyi, sadece başka bir çözümü belirttiği fikrini tutmuyorum.

Enum değerleri kesinlikle 0 - 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;
    }
}

Enum değerleri bitişikse ve enumun ilk ve son elemanını sağlayabilirseniz, o zaman:

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

ama bu kesinlikle numaralandırmıyor, sadece döngü yapıyoruz. İkinci yöntem ise diğer tüm yaklaşımlardan çok daha hızlı.

15
nawfal

dDL için seçim seçenekleri oluşturma çalışma örneği

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()
      };
12
jhilden
foreach (Suit suit in Enum.GetValues(typeof(Suit)))
{
}

(Mevcut kabul edilmiş cevap gerekli olmadığını düşündüğüm bir alçıya sahip (yanılsam da).)

10
matt burns

Bu soru, " C # Adım 2013 " Adım 10’da görünmektedir.

Yazar bir çift Numaralandırıcıdan yineleme yapmak için çift döngü 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, Suit ve Value hem numaralandırmalardır:

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

ve PlayingCard, Suit ve Value tanımlı bir kart nesnesidir:

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

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

Bunun biraz dağınık olduğunu biliyorum ama tek gömleklerin hayranıysanız, işte bir tane:

((Suit[])Enum.GetValues(typeof(Suit))).ToList().ForEach(i => DoSomething(i));
8
anar khalilov

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

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

getListOfEnum yöntemi, herhangi bir enum türünü almak için yansıma kullanır ve tüm enum değerlerinin bir IEnumerable değerini 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));
}
7
Slappywag

Bir enumu etkileşime girebileceğ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>();
7
Gabriel

Gibi sınıfınıza public static IEnumerable<T> GetValues<T>() yöntemi ekleyin

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

enum'unuzu çağırın ve iletin, şimdi foreach komutunu kullanarak yineleyebilirsiniz.

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

enum türlerine "numaralandırma türleri" denir ("numaralandırılmış" değerleri olan kaplar oldukları için değil), ancak bu tür bir değişken için olası değerleri numaralandırıyor ile tanımlanırlar.

(Aslında, bundan biraz daha karmaşıktır - enum türlerinin bir "altta yatan" tamsayı tipine sahip olduğu kabul edilir; bu, her enum değerinin bir tamsayı değerine karşılık geldiği anlamına gelir (bu genellikle örtüktür, ancak manuel olarak belirtilebilir). bu şekilde "/" adında bir değer olmasa bile, bu türden herhangi bir tamsayıyı enum değişkenine yerleştirebileceksiniz.

System.Enum.GetNames yöntemi , adından da anlaşılacağı gibi, enum değerlerinin adları olan bir dizi dizeyi almak için kullanılabilir.

EDIT: Bunun yerine System.Enum.GetValues ​​ methodunu önermeliydim. Hata.

1
Emily Chen

Ayrıca, enumun genel statik üyelerine yansıma kullanarak doğrudan bağlanabilirsiniz:

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