enums - الحصول على قيمة int من التعداد في C#




casting (21)

نظرًا لأن Enums يمكن أن يكون أي نوع متكامل ( byte و int و short وما إلى ذلك) ، فإن الطريقة الأكثر قوة للحصول على القيمة التكاملية الأساسية للتعداد هي استخدام أسلوب GetTypeCode بالتزامن مع فئة Convert :

enum Sides {
    Left, Right, Top, Bottom
}
Sides side = Sides.Bottom;

object val = Convert.ChangeType(side, side.GetTypeCode());
Console.WriteLine(val);

يجب أن يعمل هذا بغض النظر عن نوع التكامل الأساسي.

لدي فئة تسمى Questions (جمع). في هذا الصف يوجد تعداد يسمى Question (مفرد) يشبه هذا.

public enum Question
{
    Role = 2,
    ProjectFunding = 3,
    TotalEmployee = 4,
    NumberOfServers = 5,
    TopBusinessConcern = 6
}

في فئة Questions ، لدي وظيفة get(int foo) تقوم بإرجاع كائن Questions لهذا foo . هل هناك طريقة سهلة للحصول على القيمة الصحيحة من التعداد حتى يمكنني القيام بشيء مثل Questions.Get(Question.Role) ؟


في Vb. يجب أن يكون

Public Enum Question
    Role = 2
    ProjectFunding = 3
    TotalEmployee = 4
    NumberOfServers = 5
    TopBusinessConcern = 6
End Enum

Private value As Integer = CInt(Question.Role)

إذا كنت ترغب في الحصول على عدد صحيح لقيمة التعداد التي يتم تخزينها في متغير ، فكلما كان النوع هو Question ، لاستخدامه على سبيل المثال في طريقة ما ، يمكنك ببساطة القيام بهذا الأمر الذي كتبته في هذا المثال:

enum Talen
{
    Engels = 1, Italiaans = 2, Portugees = 3, Nederlands = 4, Duits = 5, Dens = 6
}

Talen Geselecteerd;    

public void Form1()
{
    InitializeComponent()
    Geselecteerd = Talen.Nederlands;
}

// You can use the Enum type as a parameter, so any enumeration from any enumerator can be used as parameter
void VeranderenTitel(Enum e)
{
    this.Text = Convert.ToInt32(e).ToString();
}

سيؤدي ذلك إلى تغيير عنوان النافذة إلى 4 لأن المتغير Geselecteerd هو Talen.Nederlands . إذا قمت بتغييره إلى Talen.Portugees واستدعاء الطريقة مرة أخرى ، سيتغير النص إلى 3.

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


فقط ألقى التعداد ، على سبيل المثال

int something = (int) Question.Role;

سيعمل ما سبق على الغالبية العظمى من التعدادات التي تراها في البرية ، لأن النوع الأساسي الافتراضي للتعداد هو int .

ومع ذلك ، وكما يشير cecilphillip ، يمكن أن يكون cecilphillip أنواع أساسية مختلفة. إذا تم التصريح عن التعداد على أنه uint ، أو long ، أو ulong ، فيجب إدراجه إلى نوع التعداد ؛ على سبيل المثال ل

enum StarsInMilkyWay:long {Sun = 1, V645Centauri = 2 .. Wolf424B = 2147483649};

يجب عليك استخدامها

long something = (long)StarsInMilkyWay.Wolf424B;

int number = Question.Role.GetHashCode();

number يجب أن يكون القيمة 2 .


ربما فاتني ذلك ولكن حاول أي شخص طريقة تمديد عامة بسيطة. هذا يعمل بشكل جيد بالنسبة لي. يمكنك تجنب الكتابة في واجهة برمجة التطبيقات بهذه الطريقة ، ولكنها في النهاية تؤدي إلى إجراء عملية تغيير نوع. هذه حالة جيدة للبرمجة Roselyn لجعل المحول البرمجي يقوم بإنشاء أسلوب GetValue لك.

    public static void Main()
    {
        int test = MyCSharpWrapperMethod(TestEnum.Test1);

        Debug.Assert(test == 1);
    }

    public static int MyCSharpWrapperMethod(TestEnum customFlag)
    {
        return MyCPlusPlusMethod(customFlag.GetValue<int>());
    }

    public static int MyCPlusPlusMethod(int customFlag)
    {
        //Pretend you made a PInvoke or COM+ call to C++ method that require an integer
        return customFlag;
    }

    public enum TestEnum
    {
        Test1 = 1,
        Test2 = 2,
        Test3 = 3
    }
}

public static class EnumExtensions
{
    public static T GetValue<T>(this Enum enumeration)
    {
        T result = default(T);

        try
        {
            result = (T)Convert.ChangeType(enumeration, typeof(T));
        }
        catch (Exception ex)
        {
            Debug.Assert(false);
            Debug.WriteLine(ex);
        }

        return result;
    }
}    

الحل الأسهل الذي يمكنني التفكير فيه هو زيادة الحمل Get(int) طريقة Get(int) مثل:

[modifiers] Questions Get(Question q)
{
    return Get((int)q);
}

حيث يمكن أن تكون [modifiers] كما في طريقة Get(int) . إذا لم تتمكن من تحرير فئة Questions أو لسبب ما لا ترغب في ذلك ، فيمكنك التحميل فوق الأسلوب بكتابة ملحق:

public static class Extensions
{
    public static Questions Get(this Questions qs, Question q)
    {
        return qs.Get((int)q);
    }
}

ماذا عن طريقة التمديد بدلاً من ذلك:

public static class ExtensionMethods
{
    public static int IntValue(this Enum argEnum)
    {
        return Convert.ToInt32(argEnum);
    }
}

والاستخدام هو أجمل قليلا:

var intValue = Question.Role.IntValue();

جرب هذا :

int value = YourEnum.ToString("D");

المثال الذي أود اقتراحه "للحصول على قيمة" int "من التعداد هو"

public enum Sample
{Book =1, Pen=2, Pencil =3}

int answer = (int)Sample.Book;

الآن سيكون الجواب 1.

آمل أن هذا قد يساعد شخص ما.


في ملاحظة ذات صلة ، إذا كنت ترغب في الحصول على قيمة int من System.Enum ، عندئذٍ هنا e :

Enum e = Question.Role;

يمكنك استخدام:

int i = Convert.ToInt32(e);
int i = (int)(object)e;
int i = (int)Enum.Parse(e.GetType(), e.ToString());
int i = (int)Enum.ToObject(e.GetType(), e);

آخر اثنين من القبيح. أنا أفضل أول واحد.


بلدي fav الإختراق int أو enums أصغر:

GetHashCode();

للحصول على التعداد

public enum Test
{
    Min = Int32.MinValue,
    One = 1,
    Max = Int32.MaxValue,
}

هذه

var values = Enum.GetValues(typeof(Test));

foreach (var val in values) 
{
    Console.WriteLine(val.GetHashCode());
    Console.WriteLine(((int)val));
    Console.WriteLine(val);
}

المخرجات

one
1
1  
max
2147483647
2147483647    
min
-2147483648
-2147483648    

إخلاء المسؤولية: لا يعمل التعداد على أساس طويل


Question question = Question.Role;
int value = (int) question;

سيؤدي إلى value == 2 .


طريقة أخرى للقيام بذلك:

Console.WriteLine("Name: {0}, Value: {0:D}", Question.Role);

سوف يؤدي إلى:

Name: Role, Value: 2

أعلن أنه طبقة ثابتة بها ثوابت عامة:

public static class Question
{
    public const int Role = 2;
    public const int ProjectFunding = 3;
    public const int TotalEmployee = 4;
    public const int NumberOfServers = 5;
    public const int TopBusinessConcern = 6;
}

ومن ثم يمكنك الإشارة إليه على أنه Question.Role ، ويتم تقييمه دائمًا إلى int أو ما تعرفه به.


public enum QuestionType
{
    Role = 2,
    ProjectFunding = 3,
    TotalEmployee = 4,
    NumberOfServers = 5,
    TopBusinessConcern = 6
}

... هو تصريح جيد.

يجب عليك إرسال النتيجة إلى int مثل:

int Question = (int)QuestionType.Role

خلاف ذلك ، لا يزال النوع QuestionType .

هذا المستوى من الصرامة هو طريقة C #.

بديل واحد هو استخدام تعريف الفصل بدلاً من ذلك:

public class QuestionType
{
    public static int Role = 2,
    public static int ProjectFunding = 3,
    public static int TotalEmployee = 4,
    public static int NumberOfServers = 5,
    public static int TopBusinessConcern = 6
}

إنه أقل أناقة للإعلان ، ولكنك لست بحاجة إلى إرساله في الكود:

int Question = QuestionType.Role

بدلا من ذلك ، قد تشعر براحة أكبر مع Visual Basic ، الذي يلبي هذا النوع من التوقعات في العديد من المجالات.


لضمان وجود قيمة التعداد ثم تحليلها ، يمكنك أيضًا القيام بما يلي.

// Fake Day of Week
string strDOWFake = "SuperDay";
// Real Day of Week
string strDOWReal = "Friday";
// Will hold which ever is the real DOW.
DayOfWeek enmDOW;

// See if fake DOW is defined in the DayOfWeek enumeration.
if (Enum.IsDefined(typeof(DayOfWeek), strDOWFake))
{
// This will never be reached since "SuperDay" 
// doesn't exist in the DayOfWeek enumeration.
    enmDOW = (DayOfWeek)Enum.Parse(typeof(DayOfWeek), strDOWFake);
}
// See if real DOW is defined in the DayOfWeek enumeration.
else if (Enum.IsDefined(typeof(DayOfWeek), strDOWReal))
{
    // This will parse the string into it's corresponding DOW enum object.
    enmDOW = (DayOfWeek)Enum.Parse(typeof(DayOfWeek), strDOWReal);
}

// Can now use the DOW enum object.
Console.Write("Today is " + enmDOW.ToString() + ".");

آمل أن يساعد هذا.


بما أن التعداد يمكن الإعلان عنه بأنواع بدائية متعددة ، فإن طريقة التمديد العامة لإدخال أي نوع تعداد يمكن أن تكون مفيدة.

        enum Box
        {
            HEIGHT,
            WIDTH,
            DEPTH
        }

        public static void UseEnum()
        {
            int height = Box.HEIGHT.GetEnumValue<int>();
            int width = Box.WIDTH.GetEnumValue<int>();
            int depth = Box.DEPTH.GetEnumValue<int>();
        }

        public static T GetEnumValue<T>(this object e) => (T)e;

مثال:

Public Enum EmpNo
{
    Raj = 1
    Rahul,
    Priyanka
}

وفي الشفرة وراء الحصول على قيمة التعداد:

int setempNo = (int)EmpNo.Raj; //This will give setempNo = 1

أو

int setempNo = (int)EmpNo.Rahul; //This will give setempNo = 2

سيتم زيادة التعداد بمقدار 1 ، ويمكنك تعيين قيمة البدء. عدا ذلك سيتم تعيينه ك 0 في البداية.


لقد قمت مؤخراً بتحويل بعيداً عن استخدام enums في التعليمة البرمجية الخاصة بي بدلاً من استخدام الفئات مع المنشئ المحمي و المثيلات الثابتة المعرفة مسبقًا (بفضل RELELF - C # ضمان قيم التعداد الصالحة - طريقة Futureproof ).

في ضوء ذلك ، فيما يلي كيفية التعامل مع هذه المشكلة الآن (بما في ذلك التحويل الضمني من / إلى int ).

public class Question
{
    // Attributes
    protected int index;
    protected string name;
    // Go with a dictionary to enforce unique index
    //protected static readonly ICollection<Question> values = new Collection<Question>();
    protected static readonly IDictionary<int,Question> values = new Dictionary<int,Question>();

    // Define the "enum" values
    public static readonly Question Role = new Question(2,"Role");
    public static readonly Question ProjectFunding = new Question(3, "Project Funding");
    public static readonly Question TotalEmployee = new Question(4, "Total Employee");
    public static readonly Question NumberOfServers = new Question(5, "Number of Servers");
    public static readonly Question TopBusinessConcern = new Question(6, "Top Business Concern");

    // Constructors
    protected Question(int index, string name)
    {
        this.index = index;
        this.name = name;
        values.Add(index, this);
    }

    // Easy int conversion
    public static implicit operator int(Question question) =>
        question.index; //nb: if question is null this will return a null pointer exception

    public static implicit operator Question(int index) =>        
        values.TryGetValue(index, out var question) ? question : null;

    // Easy string conversion (also update ToString for the same effect)
    public override string ToString() =>
        this.name;

    public static implicit operator string(Question question) =>
        question?.ToString();

    public static implicit operator Question(string name) =>
        name == null ? null : values.Values.FirstOrDefault(item => name.Equals(item.name, StringComparison.CurrentCultureIgnoreCase));


    // If you specifically want a Get(int x) function (though not required given the implicit converstion)
    public Question Get(int foo) =>
        foo; //(implicit conversion will take care of the conversion for you)
}

تكمن ميزة هذا الأسلوب في حصولك على كل ما يمكنك الحصول عليه من التعداد ، لكن شفرتك أصبحت الآن أكثر مرونة ، لذا يجب عليك تنفيذ إجراءات مختلفة بناءً على قيمة Question ، يمكنك وضع المنطق في Question نفسه (أي في فضلت أزياء OO) في مقابل وضع الكثير من عبارات الحالة في جميع أنحاء التعليمات البرمجية الخاصة بك لمعالجة كل سيناريو.

ملاحظة: تم تحديث الإجابة 2018-04-27 للاستفادة من ميزات C # 6 ؛ أي تعبيرات الإعلان والتعريفات الجسم تعبير امدا. راجع سجل النُسخ السابقة للشفرة الأصلية. هذا له فائدة من جعل التعريف أقل قليلا مطولاً. التي كانت واحدة من الشكاوى الرئيسية حول نهج هذه الإجابة.


بالنسبة للقيم الرقمية ، يعد هذا أكثر أمانًا حيث إنه سيعرض أي كائن مهما كان:

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






c# enums casting int