c# - كيف يمكنني تعداد إنوم؟


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

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

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

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

ويعطي الخطأ التالي في تجميع البيانات:

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

فشل في الكلمة الرئيسية Suit ، والثانية.



Answers



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



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

يجب أن تكون المزينة نفسها مزينة مع فلاجساتريبوت

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



بعض الإصدارات من إطار .NET لا تدعم Enum.GetValues . وهنا حل جيد من الأفكار 2.0: Enum.GetValues ​​في الإطار المضغوط :

public List<Enum> GetValues(Enum enumeration)
{
   List<Enum> enumerations = new List<Enum>();
   foreach (FieldInfo fieldInfo in enumeration.GetType().GetFields(
         BindingFlags.Static | BindingFlags.Public))
   {
      enumerations.Add((Enum)fieldInfo.GetValue(enumeration));
   }
   return enumerations;
}

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




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



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

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

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




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

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

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



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



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

Enum.GetNames(Suit)



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



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

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

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

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

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




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

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

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




يمكنني استخدام توسترينغ () ثم تقسيم وتحليل مصفوفة البصق في الأعلام.

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



ثلاث طرق:

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



هناك طريقتان لتكرار 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
}



أنا لا أحمل رأي هذا هو أفضل، أو حتى جيدة، مجرد ذكر حل آخر.

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

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




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

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> ، ولكن هذا يشتري لك شيئا هنا.




هنا مثال عملي لإنشاء خيارات تحديد ل دل

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



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

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




يظهر هذا السؤال في الفصل 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;
    }
}



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

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



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

الاستعمال:

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



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

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



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



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

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

يمكن استخدام طريقة جيتناميس لاسترداد صفيف من السلاسل التي هي أسماء قيم الأينوم، كما يوحي الاسم.