سؤال

لدي فصل يسمى 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)?

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

المحلول

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

int something = (int) Question.Role;

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

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

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

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

long something = (long)StarsInMilkyWay.Wolf424B;

نصائح أخرى

منذ أن تكون العادة أي نوع لا يتجزأ (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);

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

أعلن أنه فئة ثابتة وجود ثوابت عامة:

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 أو كل ما تحدده كما.

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

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

في مذكرة ذات صلة، إذا كنت ترغب في الحصول على 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);

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

من الأسهل مما تعتقد - تعينا بالفعل int. يحتاج فقط إلى تذكير:

int y = (int)Question.Role;
Console.WriteLine(y); // prints 2

مثال:

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 في البداية.

لقد قمت مؤخرا بتحويلها من استخدام العتاد في التعليمات البرمجية الخاصة بي لصالح بدلا من ذلك باستخدام الفصول مع منشئين محميين والحالات الثابتة المحددة مسبقا (بفضل Roelof - C # ضمان قيم الإناث صالحة - طريقة مقبل المقبلة).

في ضوء ذلك، أدناه كيف تقترب الآن من هذه المشكلة (بما في ذلك التحويل الضمني من / إلى 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 المفضلة) بدلا من وضع الكثير من بيانات الحالة طوال التعليمات البرمجية الخاصة بك لمعالجة كل سيناريو.


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

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

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

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

// 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() + ".");

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

ربما فاتني ذلك ولكن هل حاول أي شخص طريقة تمديد عام بسيط. هذا يعمل عظيم بالنسبة لي. يمكنك تجنب المطالبة بالنوع في واجهة برمجة التطبيقات الخاصة بك بهذه الطريقة ولكن في النهاية يؤدي ذلك إلى تشغيل نوع التغيير. هذه حالة جيدة لبرمجة ROSLYN لتناول مترجم يقوم بعمل طريقة 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;
    }
}    

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

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

سوف يؤدي إلى:

Name: Role, Value: 2
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، مما يلبي هذا النوع من التوقعات في العديد من المناطق.

يمكنك القيام بذلك عن طريق تنفيذ طريقة التمديد إلى نوع المعين المحدد:

public static class MyExtensions
{
    public static int getNumberValue(this Question questionThis)
    {
        return (int)questionThis;
    }
}

هذا يبسط الحصول على القيمة الدولية لقيمة العادة الحالية:

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

أو

int value = Question.Role.getNumberValue();
int number = Question.Role.GetHashCode();

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

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

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

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

var intValue = Question.Role.IntValue();
public enum Suit : int
{
    Spades = 0,
    Hearts = 1,
    Clubs = 2,
    Diamonds = 3
}

Console.WriteLine((int)(Suit)Enum.Parse(typeof(Suit), "Clubs"));

//from int
Console.WriteLine((Suit)1);

//From number you can also
Console.WriteLine((Suit)Enum.ToObject(typeof(Suit), 1));

if (typeof(Suit).IsEnumDefined("Spades"))
{
    var res = (int)(Suit)Enum.Parse(typeof(Suit), "Spades");
    Console.Out.WriteLine("{0}", res);
}

بلدي fav hack مع int int أو أصغر:

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    

تنصل:لا يعمل من أجل العتاد على أساس طويلة

فيما يلي طريقة التمديد

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

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

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;

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

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

int answer = (int)Sample.Book;

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

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

أسهل الحل الذي يمكنني التفكير فيه هو التحميل الزائد 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);
    }
}

جرب هذا واحد بدلا من تحويل ENUM إلى INT:

public static class ReturnType
{
    public static readonly int Success = 1;
    public static readonly int Duplicate = 2;
    public static readonly int Error = -1;        
}

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

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

Private value As Integer = CInt(Question.Role)

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

public static class EnumEx
{
    public static dynamic Value(this Enum e)
    {
        switch (e.GetTypeCode())
        {
        case TypeCode.Byte:
            {
                return (byte) (IConvertible) e;
            }
        case TypeCode.Int16:
            {
                return (short) (IConvertible) e;
            }
        case TypeCode.Int32:
            {
                return (int) (IConvertible) e;
            }
        case TypeCode.Int64:
            {
                return (long) (IConvertible) e;
            }
        case TypeCode.UInt16:
            {
                return (ushort) (IConvertible) e;
            }
        case TypeCode.UInt32:
            {
                return (uint) (IConvertible) e;
            }
        case TypeCode.UInt64:
            {
                return (ulong) (IConvertible) e;
            }
        case TypeCode.SByte:
            {
                return (sbyte) (IConvertible) e;
            }
        }

        return 0;
    }
Question question = Question.Role;
int value = question.GetHashCode();

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

هذا صحيح فقط إذا كان يناسب المعهد داخل int

جرب هذا :

int value = YourEnum.ToString("D");
مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top