سؤال

كيف يمكن ل int يلقي إلى enum شركة#؟

هل كانت مفيدة؟

المحلول

من سلسلة:

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.")

من int:

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

إذا نظرت إليها من وجهة نظر IL، فإن التعداد (العادي، int) يبدو كما يلي:

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

في هذه المرحلة أود أن أشير إلى ذلك System.Enum هو نوع القيمة، وهو ما يعني في الأساس ذلك BarFlag سوف يستغرق 4 بايت في الذاكرة و Foo سوف يستغرق 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 }

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

فيما يلي فئة فائدة لطيفة لـ Enums

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

إذا كنت مستعدًا للإصدار 4.0 .شبكة الإطار، هناك جديد التعداد.TryParse() وظيفة مفيدة للغاية وتعمل بشكل جيد مع السمة [الأعلام].يرى طريقة Enum.TryParse (سلسلة، TEnum%)

إذا كان لديك عدد صحيح يعمل كقناع نقطي ويمكن أن يمثل قيمة واحدة أو أكثر في تعداد [Flags]، فيمكنك استخدام هذا الرمز لتحليل قيم العلامة الفردية في القائمة:

for (var flagIterator = 0; flagIterator < 32; flagIterator++)
{
    // Determine the bit value (1,2,4,...,Int32.MinValue)
    int bitValue = 1 << flagIterator;

    // Check to see if the current flag exists in the bit mask
    if ((intValue & bitValue) != 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), bitValue))
            Console.WriteLine((MyEnum)bitValue);
    }
}

لاحظ أن هذا يفترض أن النوع الأساسي لـ enum هو عدد صحيح 32 بت.إذا كان نوعًا رقميًا مختلفًا، فسيتعين عليك تغيير الرقم 32 المشفر ليعكس البتات في هذا النوع (أو اشتقاقه برمجيًا باستخدام Enum.GetUnderlyingType())

في بعض الأحيان يكون لديك كائن ل MyEnum يكتب.يحب

var MyEnumType = typeof(MyEnumType);

ثم:

Enum.ToObject(typeof(MyEnum), 3)

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

public static bool TryConvertToEnum<T>(this int instance, out T result)
  where T: Enum
{
  var enumType = typeof (T);
  var success = Enum.IsDefined(enumType, instance);
  if (success)
  {
    result = (T)Enum.ToObject(enumType, instance);
  }
  else
  {
    result = default(T);
  }
  return success;
}

enter image description here

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

يتم تنفيذ الكود كما هو موضح أدناه حيث يكون "الأحمر" هو السلسلة و"MyColors" هو اللون ENUM الذي يحتوي على ثوابت اللون.

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

الابتعاد قليلا عن السؤال الأصلي، ولكن وجدت إجابة على سؤال Stack Overflow الحصول على قيمة 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;
}

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

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

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

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

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

في حالتي، كنت بحاجة إلى إرجاع التعداد من خدمة WCF.كنت بحاجة أيضًا إلى اسم مألوف، وليس فقط enum.ToString().

ها هي فئة WCF الخاصة بي.

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

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

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

ملحوظة: أحاول هنا تحليل القيمة إلى int، لأن التعداد يكون افتراضيًا كثافة العملياتإذا قمت بتعريف التعداد مثل هذا وهو بايت يكتب.

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

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

وإليك طريقة التمديد الذي يلقي Int32 ل Enum.

إنه يحترم إشارات البت حتى عندما تكون القيمة أعلى من الحد الأقصى الممكن.على سبيل المثال إذا كان لديك التعداد مع الاحتمالات 1, 2, ، و 4, ، لكن int هو 9, ، فإنه يفهم ذلك 1 في غياب أ 8.يتيح لك ذلك إجراء تحديثات البيانات قبل تحديثات التعليمات البرمجية.

   public static TEnum ToEnum<TEnum>(this int val) where TEnum : struct, IComparable, IFormattable, IConvertible
    {
        if (!typeof(TEnum).IsEnum)
        {
            return default(TEnum);
        }

        if (Enum.IsDefined(typeof(TEnum), val))
        {//if a straightforward single value, return that
            return (TEnum)Enum.ToObject(typeof(TEnum), val);
        }

        var candidates = Enum
            .GetValues(typeof(TEnum))
            .Cast<int>()
            .ToList();

        var isBitwise = candidates
            .Select((n, i) => {
                if (i < 2) return n == 0 || n == 1;
                return n / 2 == candidates[i - 1];
            })
            .All(y => y);

        var maxPossible = candidates.Sum();

        if (
            Enum.TryParse(val.ToString(), out TEnum asEnum)
            && (val <= maxPossible || !isBitwise)
        ){//if it can be parsed as a bitwise enum with multiple flags,
          //or is not bitwise, return the result of TryParse
            return asEnum;
        }

        //If the value is higher than all possible combinations,
        //remove the high imaginary values not accounted for in the enum
        var excess = Enumerable
            .Range(0, 32)
            .Select(n => (int)Math.Pow(2, n))
            .Where(n => n <= val && n > 0 && !candidates.Contains(n))
            .Sum();

        return Enum.TryParse((val - excess).ToString(), out asEnum) ? asEnum : default(TEnum);
    }

الطريقة السهلة والواضحة لإرسال int إلى enum في c#:

 public class Program
    {
        public enum Color : int
        {
            Blue = 0,
            Black = 1,
            Green = 2,
            Gray = 3,
            Yellow =4
        }

        public static void Main(string[] args)
        {
            //from string
            Console.WriteLine((Color) Enum.Parse(typeof(Color), "Green"));

            //from int
            Console.WriteLine((Color)2);

            //From number you can also
            Console.WriteLine((Color)Enum.ToObject(typeof(Color) ,2));
        }
    }

يمكنك ببساطة استخدام تحويل صريح يلقي int إلى التعداد أو التعداد إلى int

class Program
    {
        static void Main(string[] args)
        {
            Console.WriteLine((int)Number.three); //Output=3

            Console.WriteLine((Number)3);// Outout three
            Console.Read();
        }

        public enum Number 
        {
            Zero = 0,
            One = 1,
            Two = 2,
            three = 3           
        }
    }
مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top