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




.net enums (18)

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

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

https://code.i-harness.com

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

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

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

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

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

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

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


मुझे राय नहीं है कि यह बेहतर है, या यहां तक ​​कि अच्छा है, बस एक और समाधान बता रहा है।

यदि 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;
    }
}

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


आपको सिल्वरलाइट में 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 के सार्वजनिक स्थिर सदस्यों से जुड़ सकते हैं:

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

एनम को फिर से शुरू करने के दो तरीके हैं:

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
}

क्या होगा यदि आपको पता है कि प्रकार एक 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));
}

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

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

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

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

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

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
}

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


यह मुझे लगता है कि आप वास्तव में मूल्यों के बजाय प्रत्येक 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());
    }
}

यहां एक डीडीएल के लिए चयन विकल्प बनाने का एक कामकाजी उदाहरण है

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

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

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

वहां आप IEnumerable<Suit>


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

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

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

संपादित करें: इसके बजाय System.Enum.GetValues विधि का सुझाव दिया जाना चाहिए था। उफ़।


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

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


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




enumeration