c# - सी # में enum करने के लिए int कास्ट



10 Answers

बस इसे कास्ट करें:

MyEnum e = (MyEnum)3;

आप जांच सकते हैं कि यह Enum.IsDefined का उपयोग कर सीमा में है Enum.IsDefined :

if (Enum.IsDefined(typeof(MyEnum), 3)) { ... }
c# enums casting

सी # में एक enum लिए एक int कैसे डाला जा सकता है?




मुझे पूरा जवाब मिलना है, लोगों को यह जानना है कि एनईटी में आंतरिक रूप से कैसे काम करता है।

कितना रद्दी निर्माण कार्य है

.NET में एक enum एक संरचना है जो मानों (फ़ील्ड) के सेट को मूल प्रकार (डिफ़ॉल्ट int ) पर मैप करती है। हालांकि, आप वास्तव में अभिन्न प्रकार का चयन कर सकते हैं जो आपके enum मानचित्र को:

public enum Foo : short

इस मामले में enum को short डेटा प्रकार में मैप किया जाता है, जिसका अर्थ यह है कि इसे स्मृति में एक छोटा सा रूप में संग्रहीत किया जाएगा और जब आप इसे कास्ट करेंगे और इसका उपयोग करेंगे तो उतना ही कम व्यवहार करेंगे।

यदि आप इसे आईएल पॉइंट व्यू से देखते हैं, तो एक (सामान्य, int) enum इस तरह दिखता है:

.class public auto ansi serializable sealed BarFlag extends System.Enum
{
    .custom instance void System.FlagsAttribute::.ctor()
    .custom instance void ComVisibleAttribute::.ctor(bool) = { bool(true) }

    .field public static literal valuetype BarFlag AllFlags = int32(0x3fff)
    .field public static literal valuetype BarFlag Foo1 = int32(1)
    .field public static literal valuetype BarFlag Foo2 = int32(0x2000)

    // and so on for all flags or enum values

    .field public specialname rtspecialname int32 value__
}

यहां आपका ध्यान क्या होना चाहिए कि value__ को enum मानों से अलग से संग्रहीत किया जाता है। उपरोक्त enum Foo के मामले में, value__ का प्रकार int16 है। इसका मूल रूप से मतलब है कि जब तक आप प्रकार मिलान करते हैं , तब तक आप जो भी चाहते हैं उसे स्टोर कर सकते हैं।

इस बिंदु पर मैं उस System.Enum को इंगित करना चाहता हूं। BarFlag एक वैल्यू टाइप है, जिसका मूल रूप से मतलब है कि BarFlag मेमोरी में 4 बाइट लेगा और Foo 2 ले जाएगा - उदाहरण के लिए अंतर्निहित प्रकार का आकार (यह वास्तव में और अधिक है उससे जटिल, लेकिन हे ...)।

उत्तर

इसलिए, यदि आपके पास एक पूर्णांक है जिसे आप एक enum पर मैप करना चाहते हैं, तो रनटाइम को केवल 2 चीजें करना पड़ता है: 4 बाइट्स कॉपी करें और इसे कुछ और नाम दें (enum का नाम)। प्रतिलिपि अंतर्निहित है क्योंकि डेटा को मूल्य प्रकार के रूप में संग्रहीत किया जाता है - इसका मूल रूप से अर्थ है कि यदि आप अप्रबंधित कोड का उपयोग करते हैं, तो आप डेटा कॉपी किए बिना बस enums और integers का आदान-प्रदान कर सकते हैं।

इसे सुरक्षित बनाने के लिए, मुझे लगता है कि यह जानने का सबसे अच्छा अभ्यास है कि अंतर्निहित प्रकार समान या निहित रूप से परिवर्तनीय हैं और यह सुनिश्चित करने के लिए कि enum मान मौजूद हैं (वे डिफ़ॉल्ट रूप से चेक नहीं किए जाते हैं!)।

यह कैसे काम करता है यह देखने के लिए, निम्न कोड आज़माएं:

public enum MyEnum : int
{
    Foo = 1,
    Bar = 2,
    Mek = 5
}

static void Main(string[] args)
{
    var e1 = (MyEnum)5;
    var e2 = (MyEnum)6;

    Console.WriteLine("{0} {1}", e1, e2);
    Console.ReadLine();
}

ध्यान दें कि e2 को कास्टिंग भी काम करता है! इसके ऊपर संकलक परिप्रेक्ष्य से यह समझ में आता है: value__ फ़ील्ड बस 5 या 6 से भरा हुआ है और जब Console.WriteLine ToString() कॉल करता है, e1 का नाम हल हो जाता है जबकि e2 का नाम नहीं होता है।

यदि यह आपके इरादे से नहीं है, तो Enum.IsDefined(typeof(MyEnum), 6) का उपयोग यह जांचने के लिए करें कि क्या आप परिभाषित enum पर नक्शे कास्टिंग कर रहे हैं।

यह भी ध्यान रखें कि मैं enum के अंतर्निहित प्रकार के बारे में स्पष्ट हूं, भले ही संकलक वास्तव में यह जांचता है। मैं यह सुनिश्चित करने के लिए कर रहा हूं कि मैं सड़क के नीचे किसी भी आश्चर्य में भाग नहीं लेता हूं। कार्रवाई में इन आश्चर्यों को देखने के लिए, आप निम्न कोड का उपयोग कर सकते हैं (वास्तव में मैंने देखा है कि यह डेटाबेस कोड में बहुत कुछ होता है):

public enum MyEnum : short
{
    Mek = 5
}

static void Main(string[] args)
{
    var e1 = (MyEnum)32769; // will not compile, out of bounds for a short

    object o = 5;
    var e2 = (MyEnum)o;     // will throw at runtime, because o is of type int

    Console.WriteLine("{0} {1}", e1, e2);
    Console.ReadLine();
}



मैं अपने enum में int डालने के लिए कोड के इस टुकड़े का उपयोग कर रहा हूँ:

if (typeof(YourEnum).IsEnumDefined(valueToCast)) return (YourEnum)valueToCast;
else { //handle it here, if its not defined }

मुझे यह सबसे अच्छा समाधान मिल रहा है।




संख्यात्मक मूल्यों के लिए, यह सुरक्षित है क्योंकि यह किसी ऑब्जेक्ट को वापस करेगा चाहे इससे कोई फर्क नहीं पड़ता:

public static class EnumEx
{
    static public bool TryConvert<T>(int value, out T result)
    {
        result = default(T);
        bool success = Enum.IsDefined(typeof(T), value);
        if (success)
        {
            result = (T)Enum.ToObject(typeof(T), value);
        }
        return success;
    }
}



यदि आपके पास एक पूर्णांक है जो बिटमैस्क के रूप में कार्य करता है और [ध्वज] गणना में एक या अधिक मानों का प्रतिनिधित्व कर सकता है, तो आप व्यक्तिगत ध्वज मानों को एक सूची में पार्स करने के लिए इस कोड का उपयोग कर सकते हैं:

for (var flagIterator = 0x1; flagIterator <= 0x80000000; flagIterator <<= 1)
{
    // Check to see if the current flag exists in the bit mask
    if ((intValue & flagIterator) != 0)
    {
        // If the current flag exists in the enumeration, then we can add that value to the list
        // if the enumeration has that flag defined
        if (Enum.IsDefined(typeof(MyEnum), flagIterator))
            ListOfEnumValues.Add((MyEnum)flagIterator);
    }
}



यह एक झंडे की गणना जागरूक सुरक्षित कनवर्ट विधि है:

public static bool TryConvertToEnum<T>(this int instance, out T result)
  where T: struct
{
  var enumType = typeof (T);
  if (!enumType.IsEnum)
  {
    throw new ArgumentException("The generic type must be an enum.");
  }
  var success = Enum.IsDefined(enumType, instance);
  if (success)
  {
    result = (T)Enum.ToObject(enumType, instance);
  }
  else
  {
    result = default(T);
  }
  return success;
}



थोड़ा सा मूल प्रश्न से दूर हो रहा है, लेकिन मुझे स्टैक ओवरफ़्लो प्रश्न का उत्तर मिला, एनम उपयोगी से 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;
}

जाहिर है, कुछ enum प्रकार की कार्यक्षमता खो जाएगी, लेकिन डेटाबेस आईडी स्थिरांक का एक गुच्छा भंडारण के लिए, यह एक सुंदर साफ समाधान की तरह लगता है।




एक स्ट्रिंग से: (Enum.Parse तिथि से बाहर है, Enum.TryParse का उपयोग करें)

enum Importance
{}

Importance importance;

if (Enum.TryParse(value, out importance))
{
}



मेरे मामले में, मुझे डब्ल्यूसीएफ सेवा से enum वापस करने की जरूरत है। मुझे एक दोस्ताना नाम भी चाहिए, न कि enum.ToString ()।

यहां मेरी डब्ल्यूसीएफ कक्षा है।

[DataContract]
public class EnumMember
{
    [DataMember]
    public string Description { get; set; }

    [DataMember]
    public int Value { get; set; }

    public static List<EnumMember> ConvertToList<T>()
    {
        Type type = typeof(T);

        if (!type.IsEnum)
        {
            throw new ArgumentException("T must be of type enumeration.");
        }

        var members = new List<EnumMember>();

        foreach (string item in System.Enum.GetNames(type))
        {
            var enumType = System.Enum.Parse(type, item);

            members.Add(
                new EnumMember() { Description = enumType.GetDescriptionValue(), Value = ((IConvertible)enumType).ToInt32(null) });
        }

        return members;
    }
}

यहां एक्सटेंशन विधि है जो Enum से विवरण प्राप्त करती है।

    public static string GetDescriptionValue<T>(this T source)
    {
        FieldInfo fileInfo = source.GetType().GetField(source.ToString());
        DescriptionAttribute[] attributes = (DescriptionAttribute[])fileInfo.GetCustomAttributes(typeof(DescriptionAttribute), false);            

        if (attributes != null && attributes.Length > 0)
        {
            return attributes[0].Description;
        }
        else
        {
            return source.ToString();
        }
    }

कार्यान्वयन:

return EnumMember.ConvertToList<YourType>();



मैं अब और नहीं जानता जहां मुझे इस एनम एक्सटेंशन का हिस्सा मिलता है, लेकिन यह स्टैक ओवरफ्लो से है। मुझे इसके लिए खेद है! लेकिन मैंने इसे लिया और इसे ध्वज के साथ enums के लिए संशोधित किया। झंडे के साथ enums के लिए मैंने यह किया:

  public static class Enum<T> where T : struct
  {
     private static readonly IEnumerable<T> All = Enum.GetValues(typeof (T)).Cast<T>();
     private static readonly Dictionary<int, T> Values = All.ToDictionary(k => Convert.ToInt32(k));

     public static T? CastOrNull(int value)
     {
        T foundValue;
        if (Values.TryGetValue(value, out foundValue))
        {
           return foundValue;
        }

        // For enums with Flags-Attribut.
        try
        {
           bool isFlag = typeof(T).GetCustomAttributes(typeof(FlagsAttribute), false).Length > 0;
           if (isFlag)
           {
              int existingIntValue = 0;

              foreach (T t in Enum.GetValues(typeof(T)))
              {
                 if ((value & Convert.ToInt32(t)) > 0)
                 {
                    existingIntValue |= Convert.ToInt32(t);
                 }
              }
              if (existingIntValue == 0)
              {
                 return null;
              }

              return (T)(Enum.Parse(typeof(T), existingIntValue.ToString(), true));
           }
        }
        catch (Exception)
        {
           return null;
        }
        return null;
     }
  }

उदाहरण:

[Flags]
public enum PetType
{
  None = 0, Dog = 1, Cat = 2, Fish = 4, Bird = 8, Reptile = 16, Other = 32
};

integer values 
1=Dog;
13= Dog | Fish | Bird;
96= Other;
128= Null;



Related