.net - كيف أقوم بتعداد التعداد في C#؟




enums enumeration (22)

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

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

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

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

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

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

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

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

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


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

يظهر هذا السؤال في الفصل العاشر من " C # Step by Step 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;
    }
}

فقط لإضافة الحل الخاص بي ، والذي يعمل في إطار العمل المضغوط (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>();

أستخدم ToString () ثم أقوم بتقسيم صفيف البصاق وتحليله في الأعلام.

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

إضافة طريقة 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
     }
 }

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

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

Enum.GetNames(Suit)

هنا مثال عملي على إنشاء خيارات تحديد لـ 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()
      };

أعتقد أن هذا أكثر فعالية من الاقتراحات الأخرى لأنه لا يتم استدعاء 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]);
        }
    }
}

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

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

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

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

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

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

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

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
}

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

لقد سمعت شائعات غامضة بأن هذا بطيء بشكل كبير. أي أحد يعرف؟ - Orion Edwards Oct 15 '08 at 1:31 7

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

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

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


يبدو لي أنك ترغب حقًا في طباعة أسماء كل تعداد ، بدلاً من القيم. في هذه الحالة ، يبدو أن 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());
    }
}

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

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)
    {
        return (T[])Enum.GetValues(typeof (T));
    }
}

نظيفة بسيطة وبواسطة @ Jeppe-Stig-Nielsen s تعليق سريع.


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

إذا كانت قيم التعداد تتراوح بدقة من 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;
    }
}

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


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

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

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


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

المشاركة الأصلية للمدونة بواسطة إينار إنجيبريتسين :

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

ماذا لو كنت تعرف أن هذا النوع سيكون 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));
}

الابتعاد قليلا عن السؤال الأصلي ، لكنني وجدت إجابة على سؤال احصل على قيمة int من التعداد مفيدة. إنشاء فئة ثابتة مع خصائص public const int ، مما يسمح لك بجمع مجموعة من الثوابت int ذات الصلة بسهولة ، ومن ثم لا يلزم إرسالها إلى int عند استخدامها.

public static class Question
{
    public static readonly int Role = 2;
    public static readonly int ProjectFunding = 3;
    public static readonly int TotalEmployee = 4;
    public static readonly int NumberOfServers = 5;
    public static readonly int TopBusinessConcern = 6;
}

من الواضح أن بعض وظائف نوع التعداد سوف تُفقد ، ولكن من أجل تخزين مجموعة من ثوابت هوية قاعدة البيانات ، يبدو الأمر وكأنه حل أنيق.





c# .net enums enumeration