سؤال

كيف يمكنك تعداد enum شركة#؟

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

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

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

نصائح أخرى

يبدو لي أنك تريد حقًا طباعة أسماء كل تعداد، بدلاً من القيم.في أي حالة 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 Framework لا تدعم Enum.GetValues.إليك حلاً جيدًا من الأفكار 2.0: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;
}

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

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

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

ها أنت ذا IEnumerable<Suit>.

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

لن تحصل Enum.GetValues() في سيلفرلايت.

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

فقط لإضافة الحل الخاص بي، والذي يعمل في إطار عمل مضغوط (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 أكتوبر 2008 في 1:31 7

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

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

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

ثلاث طرق:

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

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

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

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

أستخدم 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);
}

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

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

إذا كنت بحاجة إلى التحقق من السرعة والنوع في وقت الإنشاء والتشغيل، فإن طريقة المساعدة هذه أفضل من استخدام 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>, لكن هذا لا يشتري لك شيئًا هنا.

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

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

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

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

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

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

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

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

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

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

يحرر:ينبغي أن اقترح System.Enum.GetValues طريقة بدلا من ذلك.أُووبس.

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

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

حاول استخدام foreach (var ite in enum.getValues ​​(typeof (Suits)))

مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top