c# - मैं सी#में एक enum कैसे गणना करते हैं?





.net enums enumeration (22)


मुझे लगता है कि यह अन्य सुझावों की तुलना में अधिक कुशल है क्योंकि हर बार आपके पास लूप होने पर 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 कैसे गणना कर सकते हैं?

जैसे निम्न कोड संकलित नहीं करता है:

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

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

और निम्नलिखित संकलन-समय त्रुटि देता है:

'सूट' एक 'प्रकार' है लेकिन इसका प्रयोग 'चर'

यह Suit कीवर्ड पर विफल रहता है, दूसरा।




यदि आपको गति और रन टाइम पर जांच और टाइप की जांच की आवश्यकता है, तो यह सहायक विधि प्रत्येक तत्व को कास्ट करने के लिए 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> वापस कर सकते हैं, लेकिन यह आपको यहां कुछ भी नहीं खरीदता है।




Cast<T> का उपयोग क्यों नहीं कर रहा है?

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

वहां आप IEnumerable<Suit>




मुझे पता है कि यह थोड़ा गन्दा है लेकिन यदि आप एक लाइनर के प्रशंसक हैं, तो यहां एक है:

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



enum प्रकारों को "गणना प्रकार" कहा जाता है क्योंकि वे कंटेनर हैं जो "गणना" मान (जो वे नहीं हैं), लेकिन क्योंकि वे उस प्रकार के चर के लिए संभावित मानों को समझाकर परिभाषित किए जाते हैं।

(असल में, यह उससे थोड़ा अधिक जटिल है - enum प्रकारों को "अंतर्निहित" पूर्णांक प्रकार माना जाता है, जिसका अर्थ है कि प्रत्येक enum मान एक पूर्णांक मान से मेल खाता है (यह आमतौर पर निहित है, लेकिन मैन्युअल रूप से निर्दिष्ट किया जा सकता है)। सी # डिज़ाइन किया गया था एक तरह से ताकि आप उस प्रकार के किसी भी पूर्णांक को enum चर में भर सकें, भले ही यह "नामित" मान न हो।)

System.Enum.GetNames विधि का उपयोग स्ट्रिंग्स की सरणी को पुनर्प्राप्त करने के लिए किया जा सकता है जो नाम मानों के नाम हैं, जैसा कि नाम बताता है।

संपादित करें: इसके बजाय System.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();
    }
}



क्या होगा यदि आपको पता है कि प्रकार एक 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 किसी भी enum प्रकार लेने के लिए प्रतिबिंब का उपयोग करता है और सभी enum मानों का एक 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));
}



मैं 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 मान 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;
    }
}

यदि enum मान संगत हैं और आप enum का पहला और अंतिम तत्व प्रदान कर सकते हैं, तो:

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

लेकिन यह कड़ाई से गणना नहीं कर रहा है, सिर्फ लूपिंग। हालांकि दूसरी विधि किसी भी अन्य दृष्टिकोण की तुलना में बहुत तेज है ...




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

मैंने अस्पष्ट अफवाहें सुनी हैं कि यह बहुत धीमी है। किसी को पता है? - ओरियन एडवर्ड्स अक्टूबर 15 '08 1:31 7 पर

मुझे लगता है कि सरणी को कैशिंग करना काफी तेज होगा। ऐसा लगता है कि आपको हर बार एक नया सरणी (प्रतिबिंब के माध्यम से) मिल रही है। बल्कि:

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

यह कम से कम थोड़ा तेज है, जे?




यह प्रश्न चरण 2013 में " सी # चरण " के अध्याय 10 में दिखाई देता है

लेखक एन्युमरेटर्स की एक जोड़ी (कार्ड का पूरा डेक बनाने के लिए) के माध्यम से दोहराने के लिए डबल फॉर-लूप का उपयोग करता है:

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



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



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

(वर्तमान स्वीकृत उत्तर में एक कलाकार है जिसे मुझे नहीं लगता है (हालांकि मैं गलत हो सकता हूं)।)




यह मुझे लगता है कि आप वास्तव में मूल्यों के बजाय प्रत्येक enum के नाम मुद्रित करना चाहते हैं। इस मामले में 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 के मूल्यों को गिनने का एक अच्छा तरीका नहीं है। आपको इसके बजाय ऐसा करना चाहिए।

मैं इसके बजाय Enum.GetValues(typeof(Suit)) उपयोग 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());
    }
}



बस मेरा समाधान जोड़ने के लिए, जो कॉम्पैक्ट फ्रेमवर्क (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>();



विधि को public static IEnumerable<T> GetValues<T>() को अपनी कक्षा में जोड़ें, जैसे

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

कॉल करें और अपने enum पास, अब आप foreach का उपयोग कर इसके माध्यम से फिर से कर सकते हैं

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



तीन तरीके से:

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 उपयोग के लिए कुछ एक्सटेंशन किए हैं, शायद कोई इसका उपयोग कर सकता है ...

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 खुद को FlagsAttribute साथ सजाया जाना चाहिए

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



मैं अपने दो पेंस को फेंक दूंगा, केवल शीर्ष उत्तरों को एक साथ जोड़कर, एक बहुत ही सरल विस्तार के साथ

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

स्वच्छ सरल और @ जेपे-स्टिग-नील्सन की टिप्पणी तेजी से।




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

जैसा कि किसी भी कोड में reflection शामिल reflection , आपको यह सुनिश्चित करने के लिए कदम उठाने चाहिए कि यह केवल एक बार चलता है और परिणाम कैश किए जाते हैं।




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



यदि आप Backbone का उपयोग कर रहे हैं, तो आप Backbone का उपयोग करके पूर्ण रूप से पूर्ण एनम कार्यक्षमता (आईडी, नाम, कस्टम सदस्यों द्वारा ढूंढें) प्राप्त कर सकते हैं।

// enum instance members, optional
var Color = Backbone.Model.extend({
    print : function() {
        console.log("I am " + this.get("name"))
    }
});

// enum creation
var Colors = new Backbone.Collection([
    { id : 1, name : "Red", rgb : 0xFF0000},
    { id : 2, name : "Green" , rgb : 0x00FF00},
    { id : 3, name : "Blue" , rgb : 0x0000FF}
], {
    model : Color
});

// Expose members through public fields.
Colors.each(function(color) {
    Colors[color.get("name")] = color;
});

// using
Colors.Red.print()




c# .net enums enumeration