it-swarm.asia

كيف يمكنني تعداد التعداد في C #؟

كيف يمكنك تعداد enum في C #؟

مثلا لا يتم ترجمة التعليمات البرمجية التالية:

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

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

ويعطي الخطأ وقت الترجمة التالي:

"البدلة" عبارة عن "نوع" ولكنها تُستخدم كـ "متغير"

فشل في الكلمة الأساسية Suit ، الثانية.

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

ملاحظة : المدلى بها إلى (Suit[]) ليست ضرورية للغاية ، لكنها تجعل الكود 0.5 نانومتر أسرع.

4232
jop

يبدو لي أنك تريد حقًا طباعة أسماء كل تعداد ، بدلاً من القيم. في هذه الحالة ، يبدو أن الدالة Enum.GetNames() هي الطريقة الصحيحة.

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

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

بالمناسبة ، زيادة القيمة ليست طريقة جيدة لتعداد قيم التعداد. يجب عليك القيام بذلك بدلا من ذلك.

أود استخدام Enum.GetValues(typeof(Suit)) بدلاً من ذلك.

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

قمت ببعض الإضافات لسهولة استخدام التعداد ، ربما يمكن لأي شخص استخدامها ...

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

يجب تزيين التعداد نفسه باستخدام FlagsAttribute

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

لا تدعم بعض إصدارات .NET Framework Enum.GetValues. إليك حلاً جيدًا من Ideas 2.0: Enum.GetValues ​​in 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;
}

كما هو الحال مع أي رمز يتضمن انعكاس ، يجب عليك اتخاذ خطوات لضمان تشغيله مرة واحدة فقط وتخزين النتائج مؤقتًا.

165
Ekevoo

لماذا لا أحد يستخدم Cast<T>؟

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

هناك تذهب IEnumerable<Suit>.

97
sircodesalot

أعتقد أن هذا أكثر فعالية من الاقتراحات الأخرى لأنه لا يتم استدعاء GetValues() في كل مرة يكون لديك حلقة. بل هو أيضا أكثر إيجازا. وتحصل على خطأ وقت الترجمة وليس استثناء وقت التشغيل إذا Suit ليس enum.

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

EnumLoop لديه هذا التعريف العام تمامًا:

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

لن تحصل على Enum.GetValues() في Silverlight.

نشر المدونة الأصلية بواسطة 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();
    }
}
72
Aubrey Taylor

فقط لإضافة الحل الخاص بي ، والذي يعمل في إطار مضغوط (3.5) ويدعم فحص النوع في وقت الترجمة :

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() ، سأكون سعيدًا لرؤية حل.

تبدو المكالمة كما يلي:

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

أعتقد أنك يمكن أن تستخدم

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

سمعت شائعات غامضة بأن هذا بطيء بشكل رهيب. أي أحد يعرف؟ - أوريون إدواردز 15 أكتوبر 2008 في 1:31 7

أعتقد أن التخزين المؤقت للصفيف سيسرعه إلى حد كبير. يبدو أنك تحصل على مجموعة جديدة (من خلال الانعكاس) في كل مرة. بدلا:

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

هذا على الأقل أسرع قليلا ، جا؟

44
Limited Atonement

ثلاث طرق:

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

لست متأكدًا من سبب عرض GetEnumValues على مثيل النوع ، فهو غير قابل للقراءة على الإطلاق بالنسبة لي.


إن وجود فصل مساعد مثل Enum<T> هو الأكثر قابلية للقراءة وتنسى بالنسبة لي:

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

أنت الآن تتصل:

Enum<Suit>.GetValues();
//or
Enum.GetValues(typeof(Suit)); //pretty consistent style

يمكن للمرء أيضًا استخدام نوع من التخزين المؤقت إذا كان الأداء مهمًا ، لكنني لا أتوقع أن تكون هذه مشكلة على الإطلاق

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

ماذا بحق الجحيم سألقي به بنسيين ، فقط من خلال الجمع بين أفضل الإجابات التي أجريها مع امتداد بسيط للغاية

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

نظيفة بسيطة وبتعليق @ جيبي ستيغ نيلسن بسرعة.

22
Darkside

هناك طريقتان لتكرار Enum:

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

الأولى ستمنحك القيم في النموذج على صفيفobject، والثاني سيمنحك القيم في شكل صفيفString.

استخدمه في حلقة foreach كما يلي:

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

إذا كنت بحاجة إلى التحقق من السرعة والكتابة في وقت البناء والتشغيل ، فإن طريقة المساعدة هذه أفضل من استخدام LINQ لإلقاء كل عنصر:

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

ويمكنك استخدامه مثل أدناه:

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

بالطبع يمكنك العودة IEnumerable<T> ، لكن هذا لا يشتري لك شيئًا هنا.

15
dmihailescu

لا أعتقد أن هذا أفضل ، أو حتى جيد ، فقط ذكر حلاً آخر.

إذا كانت قيم التعداد تتراوح بدقة من 0 إلى n - 1 ، فإن البديل العام:

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

إذا كانت قيم التعداد متجاورة ويمكنك توفير العنصر الأول والأخير من التعداد ، عندئذٍ:

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

ولكن هذا ليس التعداد بدقة ، فقط حلقات. الطريقة الثانية هي أسرع بكثير من أي نهج آخر على الرغم من ...

15
nawfal

فيما يلي مثال عملي لإنشاء خيارات تحديد لـ 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()
      };
12
jhilden
foreach (Suit suit in Enum.GetValues(typeof(Suit)))
{
}

(تحتوي الإجابة المقبولة الحالية على صورة لا أعتقد أنها ضرورية (على الرغم من أنني قد أكون مخطئًا).)

10
matt burns

يظهر هذا السؤال في الفصل 10 من " C # خطوة بخطوة 2013 "

يستخدم المؤلف حلقة مزدوجة للتكرار من خلال زوج من العدادات (لإنشاء مجموعة بطاقات كاملة):

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

في هذه الحالة ، Suit و Value كلاهما تعدادان:

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

و PlayingCard هو كائن بطاقة ذو Suit و Value:

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

أعلم أن الأمر فوضوي بعض الشيء ، لكن إذا كنت من محبي الخطوط الفردية ، فإليك واحدة:

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

ماذا لو كنت تعرف أن النوع سيكون enum ، لكنك لا تعرف ما هو النوع الدقيق في وقت الترجمة؟

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 الانعكاس لأخذ أي نوع من التعداد وإرجاع IEnumerable لجميع قيم التعداد.

الاستعمال:

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

طريقة بسيطة وعامة لتحويل التعداد إلى شيء يمكنك التفاعل:

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

وثم:

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

أضف طريقة public static IEnumerable<T> GetValues<T>() إلى فصلك ، مثل

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

استدعاء وتمرير التعداد الخاص بك ، والآن يمكنك تكرار ذلك باستخدام foreach

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

تسمى أنواع enum "أنواع التعداد" ليس لأنها عبارة عن حاويات "تعداد" القيم (التي ليست كذلك) ، ولكن لأنها محددة بواسطة التعداد القيم المحتملة لمتغير من هذا النوع.

(في الواقع ، هذا أكثر تعقيدًا من ذلك - تعتبر أنواع التعداد نوعًا صحيحًا "أساسيًا" ، مما يعني أن كل قيمة تعداد تتوافق مع قيمة عدد صحيح (هذا عادةً ما يكون ضمنيًا ، ولكن يمكن تحديده يدويًا). تم تصميم C # بطريقة بحيث يمكنك إدخال أي عدد صحيح من هذا النوع في متغير التعداد ، حتى لو لم تكن قيمة "مسمى".)

يمكن استخدام System.Enum.GetNames method لاسترداد مجموعة من السلاسل التي هي أسماء قيم التعداد ، كما يوحي الاسم.

تحرير: يجب أن يكون اقترح System.Enum.GetValues ​​ الطريقة بدلاً من ذلك. وجه الفتاة.

1
Emily Chen

كما يمكنك ربط الأعضاء الثابتة العامة للتعداد مباشرة باستخدام الانعكاس:

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