[c#] Cast int to enum in C #



Answers

فقط ألقيها:

MyEnum e = (MyEnum)3;

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

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

كيف يمكن تصوير int إلى enum في C #؟




هذا عبارة عن أسلوب تحويل آمن علم التعداد:

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



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

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

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




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

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



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

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



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

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

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



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

enum Importance
{}

Importance importance;

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






أعتقد أن الحصول على إجابة كاملة ، يجب أن يعرف الناس كيف يعمل enev داخليًا في .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) للتحقق مما إذا كانت القيمة التي 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();
}



Links