c# - يلقي إنت إلى إنوم في C #


كيف يمكن أن يلقي int إلى enum في C #؟



Answers


من سلسلة:

YourEnum foo = (YourEnum) Enum.Parse(typeof(YourEnum), yourString);
// the foo.ToString().Contains(",") check is necessary for enumerations marked with an [Flags] attribute
if (!Enum.IsDefined(typeof(YourEnum), foo) && !foo.ToString().Contains(","))
  throw new InvalidOperationException($"{yourString} is not an underlying value of the YourEnum enumeration.")

من إنت:

YourEnum foo = (YourEnum)yourInt;

تحديث:

من عدد يمكنك أيضا

YourEnum foo = (YourEnum)Enum.ToObject(typeof(YourEnum) , yourInt);



فقط يلقي عليه:

MyEnum e = (MyEnum)3;

يمكنك التحقق مما إذا كان في النطاق باستخدام Enum.IsDefined :

if (Enum.IsDefined(typeof(MyEnum), 3)) { ... }



بدلا من ذلك، استخدم طريقة التمديد بدلا من بطانة واحدة:

public static T ToEnum<T>(this string enumString)
{
    return (T) Enum.Parse(typeof (T), enumString);
}

الاستعمال:

Color colorEnum = "Red".ToEnum<Color>();

أو

string color = "Red";
var colorEnum = color.ToEnum<Color>();



وأعتقد أن الحصول على إجابة كاملة، والناس يجب أن نعرف كيف عمل إنومز داخليا في .NET.

كيف يعمل الاشياء

إن إنوم في .NET عبارة عن بنية تقوم بتعيين مجموعة من القيم (حقول) إلى نوع أساسي (الافتراضي هو int ). ومع ذلك، يمكنك في الواقع اختيار نوع التكامل الذي خرائط الأقمار إلى:

public enum Foo : short

في هذه الحالة يتم تعيين إينوم إلى نوع البيانات short ، مما يعني أنه سيتم تخزينها في الذاكرة قصيرة وسوف تتصرف كما قصيرة عندما يلقي واستخدامه.

إذا نظرتم إليه من وجهة نظر إيل، يظهر (إن، إنت) إنوم مثل هذا:

.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__ يتم تخزينها بشكل منفصل عن قيم value__ . في حالة Foo value__ أعلاه، يكون نوع value__ int16. هذا يعني في الأساس أنه يمكنك تخزين كل ما تريد في إنوم، طالما أن أنواع المباراة .

عند هذه النقطة أود أن أشير إلى أن System.Enum هو نوع القيمة، وهو ما يعني أساسا أن BarFlag سوف يستغرق 4 بايت في الذاكرة وسوف Foo يستغرق 2 - على سبيل المثال حجم النوع الأساسي (انها في الواقع أكثر معقدة من ذلك، ولكن مهلا ...).

الاجابة

لذلك، إذا كان لديك عدد صحيح الذي تريد تعيين إلى إنوم، وقت التشغيل فقط أن تفعل 2 الأشياء: نسخ 4 بايت واسمها شيء آخر (اسم التعداد). النسخ ضمني لأنه يتم تخزين البيانات كنوع القيمة - وهذا يعني أساسا أنه إذا كنت تستخدم التعليمات البرمجية غير المدارة، يمكنك ببساطة تبادل إنومز والأعداد الصحيحة دون نسخ البيانات.

ولجعله آمنا، أعتقد أنه من أفضل الممارسات أن نعرف أن الأنواع الأساسية هي نفسها أو قابلة للتحويل ضمنا ولضمان وجود قيم الإينوم (لا يتم فحصها بشكل افتراضي!).

لمعرفة كيفية عمل ذلك، جرب التعليمات البرمجية التالية:

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) للتحقق مما إذا كانت القيمة التي يتم إرسال خرائط إلى إنوم محددة.

نلاحظ أيضا أن أنا صريح حول النوع الأساسي من الإينوم، على الرغم من أن مترجم يتحقق في الواقع هذا. أنا أفعل هذا للتأكد من أنني لا تصادف أي مفاجآت على الطريق. لرؤية هذه المفاجآت في العمل، يمكنك استخدام التعليمات البرمجية التالية (في الواقع لقد رأيت هذا يحدث الكثير في رمز قاعدة البيانات):

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



خذ المثال التالي:

int one = 1;
MyEnum e = (MyEnum)one;



أنا باستخدام هذه القطعة من التعليمات البرمجية للادلاء إنت إلى بلدي إنوم:

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

أجد أنه أفضل حل.




وفيما يلي فئة فائدة لطيفة للمداخل

public static class EnumHelper
{
    public static int[] ToIntArray<T>(T[] value)
    {
        int[] result = new int[value.Length];
        for (int i = 0; i < value.Length; i++)
            result[i] = Convert.ToInt32(value[i]);
        return result;
    }

    public static T[] FromIntArray<T>(int[] value) 
    {
        T[] result = new T[value.Length];
        for (int i = 0; i < value.Length; i++)
            result[i] = (T)Enum.ToObject(typeof(T),value[i]);
        return result;
    }


    internal static T Parse<T>(string value, T defaultValue)
    {
        if (Enum.IsDefined(typeof(T), value))
            return (T) Enum.Parse(typeof (T), value);

        int num;
        if(int.TryParse(value,out num))
        {
            if (Enum.IsDefined(typeof(T), num))
                return (T)Enum.ToObject(typeof(T), num);
        }

        return defaultValue;
    }
}



بالنسبة للقيم الرقمية، يكون هذا أكثر أمانا لأنه سيعود كائن بغض النظر عن:

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



أحيانا يكون لديك كائن إلى نوع MyEnum . مثل

var MyEnumType = typeof(MyEnumType);

ثم:

Enum.ToObject(typeof(MyEnum), 3)



لتحويل سلسلة إلى إنوم أو إنت إلى إنوم ثابت نحن بحاجة إلى استخدام الدالة Enum.Parse. هنا هو فيديو يوتيوب https://www.youtube.com/watch؟v=4nhx4VwdRDk التي تظهر في الواقع مع سلسلة ونفس ينطبق على إنت.

رمز يذهب كما هو مبين أدناه حيث "الأحمر" هو سلسلة و "ميكولورس" هو إنوم اللون الذي لديه ثوابت اللون.

MyColors EnumColors = (MyColors)Enum.Parse(typeof(MyColors), "Red");



قليلا الحصول على بعيدا عن السؤال الأصلي، ولكن وجدت إجابة على سؤال المكدس تجاوز احصل على قيمة إنت من إنوم مفيدة. إنشاء فئة ثابتة مع خصائص 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;
}

ومن الواضح أن بعض وظائف نوع إنوم سوف تضيع، ولكن لتخزين مجموعة من الثوابت معرف قاعدة البيانات، يبدو وكأنه حل مرتبة جدا.




هذا هو العلم تعداد علم آمنة طريقة التحويل:

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



هذا يوزع الأعداد الصحيحة أو السلاسل إلى إنوم الهدف مع مطابقة جزئية في dot.NET 4.0 باستخدام الأدوية العامة مثل في فئة فائدة تاواني أعلاه. أنا استخدامه لتحويل المتغيرات تبديل سطر الأوامر التي قد تكون غير مكتملة. بما أنه لا يمكن أن يكون إنوم لاغيا، يجب أن توفر منطقيا قيمة افتراضية. ويمكن أن يسمى مثل هذا:

var result = EnumParser<MyEnum>.Parse(valueToParse, MyEnum.FirstValue);

إليك الشفرة:

using System;

public class EnumParser<T> where T : struct
{
    public static T Parse(int toParse, T defaultVal)
    {
        return Parse(toParse + "", defaultVal);
    }
    public static T Parse(string toParse, T defaultVal) 
    {
        T enumVal = defaultVal;
        if (defaultVal is Enum && !String.IsNullOrEmpty(toParse))
        {
            int index;
            if (int.TryParse(toParse, out index))
            {
                Enum.TryParse(index + "", out enumVal);
            }
            else
            {
                if (!Enum.TryParse<T>(toParse + "", true, out enumVal))
                {
                    MatchPartialName(toParse, ref enumVal);
                }
            }
        }
        return enumVal;
    }

    public static void MatchPartialName(string toParse, ref T enumVal)
    {
        foreach (string member in enumVal.GetType().GetEnumNames())
        {
            if (member.ToLower().Contains(toParse.ToLower()))
            {
                if (Enum.TryParse<T>(member + "", out enumVal))
                {
                    break;
                }
            }
        }
    }
}

في: كان السؤال عن الأعداد الصحيحة، والتي لم يذكر أحد سوف تتحول صراحة أيضا في Enum.TryParse ()




من سلسلة: (Enum.Parse خارج التاريخ، استخدم Enum.TryParse)

enum Importance
{}

Importance importance;

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



في حالتي، كنت بحاجة إلى إعادة الأنتوم من خدمة وف. أنا أيضا بحاجة إلى اسم ودية، وليس فقط 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;
    }
}

في ما يلي طريقة التمديد التي تحصل على الوصف من إنوم.

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



طرق مختلفة للادلاء من ومن Enum

enum orientation : byte
{
 north = 1,
 south = 2,
 east = 3,
 west = 4
}

class Program
{
  static void Main(string[] args)
  {
    orientation myDirection = orientation.north;
    Console.WriteLine(“myDirection = {0}”, myDirection); //output myDirection =north
    Console.WriteLine((byte)myDirection); //output 1

    string strDir = Convert.ToString(myDirection);
        Console.WriteLine(strDir); //output north

    string myString = north”; //to convert string to Enum
    myDirection = (orientation)Enum.Parse(typeof(orientation),myString);


 }
}



أنا لا أعرف بعد الآن حيث أحصل على جزء من هذا تمديد إينوم، وإنما هو من ستاكوفيرفلو. أنا آسف على هذا! ولكن أخذت هذا واحد وتعديله للداخل مع الأعلام. بالنسبة للأونوم مع الأعلام فعلت هذا:

  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;



وفيما يلي طريقة تمديد أفضل قليلا

public static string ToEnumString<TEnum>(this int enumValue)
        {
            var enumString = enumValue.ToString();
            if (Enum.IsDefined(typeof(TEnum), enumValue))
            {
                enumString = ((TEnum) Enum.ToObject(typeof (TEnum), enumValue)).ToString();
            }
            return enumString;
        }



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

public enum FriendType  
{
    Default,
    Audio,
    Video,
    Image
}

public static class EnumHelper<T>
{
    public static T ConvertToEnum(dynamic value)
    {
        var result = default(T);
        var tempType = 0;

        //see Note below
        if (value != null &&
            int.TryParse(value.ToString(), out  tempType) && 
            Enum.IsDefined(typeof(T), tempType))
        {
            result = (T)Enum.ToObject(typeof(T), tempType); 
        }
        return result;
    }
}

ملاحظة: هنا أحاول تحليل القيمة في إنت، لأن إنوم هو إنت إنتيفال إذا قمت بتعريف إنوم مثل هذا الذي هو نوع بايت .

public enum MediaType : byte
{
    Default,
    Audio,
    Video,
    Image
} 

تحتاج إلى تغيير تحليل في طريقة المساعد من

int.TryParse(value.ToString(), out  tempType)

إلى

byte.TryParse(value.ToString(), out tempType)

أنا التحقق من طريقة بلدي لاتباع المدخلات

EnumHelper<FriendType>.ConvertToEnum(null);
EnumHelper<FriendType>.ConvertToEnum("");
EnumHelper<FriendType>.ConvertToEnum("-1");
EnumHelper<FriendType>.ConvertToEnum("6");
EnumHelper<FriendType>.ConvertToEnum("");
EnumHelper<FriendType>.ConvertToEnum("2");
EnumHelper<FriendType>.ConvertToEnum(-1);
EnumHelper<FriendType>.ConvertToEnum(0);
EnumHelper<FriendType>.ConvertToEnum(1);
EnumHelper<FriendType>.ConvertToEnum(9);

اسف للغتى الانجليزيه