उपयोगकर्ता के अनुकूल तार के साथ Enum ToString


282

मेरी एनम में निम्नलिखित मूल्य शामिल हैं:

private enum PublishStatusses{
    NotCompleted,
    Completed,
    Error
};

मैं इन मूल्यों को उपयोगकर्ता के अनुकूल तरीके से आउटपुट करने में सक्षम होना चाहता हूं।
मुझे फिर से मूल्य से स्ट्रिंग में जाने में सक्षम होने की आवश्यकता नहीं है।



जवाबों:


350

मैं DescriptionSystem.ComponentModel नाम स्थान से विशेषता का उपयोग करता हूं । बस enum को सजाने के लिए:

private enum PublishStatusValue
{
    [Description("Not Completed")]
    NotCompleted,
    Completed,
    Error
};

फिर इसे पुनः प्राप्त करने के लिए इस कोड का उपयोग करें:

public static string GetDescription<T>(this T enumerationValue)
    where T : struct
{
    Type type = enumerationValue.GetType();
    if (!type.IsEnum)
    {
        throw new ArgumentException("EnumerationValue must be of Enum type", "enumerationValue");
    }

    //Tries to find a DescriptionAttribute for a potential friendly name
    //for the enum
    MemberInfo[] memberInfo = type.GetMember(enumerationValue.ToString());
    if (memberInfo != null && memberInfo.Length > 0)
    {
        object[] attrs = memberInfo[0].GetCustomAttributes(typeof(DescriptionAttribute), false);

        if (attrs != null && attrs.Length > 0)
        {
            //Pull out the description value
            return ((DescriptionAttribute)attrs[0]).Description;
        }
    }
    //If we have no description attribute, just return the ToString of the enum
    return enumerationValue.ToString();
}

12
इस उदाहरण को पढ़ना आसान है। stackoverflow.com/questions/1415140/…
RayLoveless

31
मुझे संदेह है कि इस समाधान में वर्णित प्रतिबिंब का उपयोग करने के लिए एक महत्वपूर्ण प्रदर्शन हिट है। ToFriendlyString एक्सटेंशन विधि का उपयोग करने के लिए विल की विधि का कोड समझना बहुत आसान है, और इसका प्रदर्शन भी बहुत तेज़ होना चाहिए।
हम्बड्स 18

1
मुझे वह संस्करण पसंद है जो @RayL से जुड़ा हुआ है क्योंकि यह केवल Enums में एक्सटेंशन विधि जोड़ देगा। अगर वह सब आप इसके लिए उपयोग करना चाहते हैं (जैसा कि इसके साथ संकेत दिया गया है ArgumentException, तो विधि पूरी तरह से सामान्य होने का कोई कारण नहीं है।
क्रिल्लार

4
इसका मतलब यह है कि हर एनम को अपनी खुद की एक्सटेंशन विधि की आवश्यकता है। यह अधिक सामान्य उपयोग है और इसके लिए अधिक काम करने की आवश्यकता होती है, लेकिन आप प्रदर्शन पर निर्णय लेने से पहले संभवतः "तेज़" का मतलब निकालना चाहते हैं।
रे बोयसेन

2
@petar काम करता है, लेकिन यदि आप उपयोगकर्ताओं के लिए अनुकूल तार प्रदर्शित नहीं करना चाहते हैं। MY_TYPE में अंडरस्कोर होगा और अनुकूलन योग्य नहीं है।
रे बोयसेन

354

मैं विस्तार विधियों के साथ ऐसा करता हूं:

public enum ErrorLevel
{
  None,
  Low,
  High,
  SoylentGreen
}

public static class ErrorLevelExtensions
{
  public static string ToFriendlyString(this ErrorLevel me)
  {
    switch(me)
    {
      case ErrorLevel.None:
        return "Everything is OK";
      case ErrorLevel.Low:
        return "SNAFU, if you know what I mean.";
      case ErrorLevel.High:
        return "Reaching TARFU levels";
      case ErrorLevel.SoylentGreen:
        return "ITS PEOPLE!!!!";
      default:
        return "Get your damn dirty hands off me you FILTHY APE!";
    }
  }
}

6
यह विशेषता जवाब की तुलना में बहुत अधिक साफ है। अच्छा!
लीव्रेव

3
@pennyrave: एह। UI घटक बहुत सारे DisplayNameAttribute और DescriptionAttribute को खोजने और उपयोग करने की अपेक्षा कर रहे हैं। वास्तव में, अब, मैं इन मूल्यों को आसानी से प्राप्त करने के लिए इन और एक विस्तार विधि का उपयोग करता हूं।

60
इस मुद्दे को मैं इसके साथ देखता हूं कि आप इन विस्तार विधियों को लगातार लिख रहे हैं। विशेषता तंत्र के साथ, यह इसे सजाने का एक सरल तरीका है और केवल एक विधि को कॉल करना है।
Ray Booysen

5
पक्का नहीं आपका क्या मतलब है?
रे बोयसेन

9
यह बेहतर है, मेरी राय में, defaultमामले के कार्यान्वयन को वापस आने की अनुमति देने के लिए me.ToString()और केवल उन मामलों के लिए स्विच केस स्टेटमेंट प्रदान करें जिन्हें आप ओवरराइड करना चाहते हैं। आपके उदाहरण में, मुझे लगता है कि वे सभी अलग-अलग हैं, लेकिन वास्तविक उपयोग के मामलों में, मुझे संदेह है कि अधिकांश एकल-शब्द enum मान पर्याप्त होंगे और आप केवल बहु-शब्द enum मानों के लिए ओवरराइड प्रदान करेंगे।
स्कॉट

78

शायद मुझे कुछ याद आ रहा है, लेकिन Enum.GetName में क्या गलत है?

public string GetName(PublishStatusses value)
{
    return Enum.GetName(typeof(PublishStatusses), value)
}

संपादित करें: उपयोगकर्ता के अनुकूल तार के लिए, आपको अंतर्राष्ट्रीयकरण / स्थानीयकरण प्राप्त करने के लिए एक .resource से गुजरने की आवश्यकता है, और यह निश्चित रूप से उसी पर एक डेकोरेटर विशेषता की तुलना में Enum कुंजी के आधार पर एक निश्चित कुंजी का उपयोग करना बेहतर होगा।


12
मैं एनम का शाब्दिक मूल्य लौटाता हूं, कुछ उपयोगकर्ता के अनुकूल नहीं।
बोरिस कॉल

2
oic - अच्छी तरह से एक बहुत बड़ा मामला है कि आपको इस मूल्य के आधार पर एक स्ट्रिंग संसाधन लाइब्रेरी से गुजरना होगा, क्योंकि वैकल्पिक (डेकोरेटर एट्रीब्यूज) I18N का समर्थन नहीं करेगा
annakata

1
I18N के मामले में, मैं एक अनुवादित स्ट्रिंग के लिए संसाधन परिवाद में गेटडेस्क्रिप्शन () विधि खोज करूँगा और विवरण में वापस गिरूंगा और फिर शाब्दिक रूप से वापस गिरूंगा।
बोरिस कॉल

3
स्थानीयकरण के लिए संसाधन कुंजी के रूप में MyEnum.ToString () के लिए +1। मैं वर्षों से कर रहा हूँ
jackvsworld

1
@annakata हमने वास्तव में l18N के लिए समर्थन शामिल करने के लिए विशेषता तंत्र को बढ़ाया है, यह वास्तव में एक साधारण बदलाव है।
रे बोयसेन

23

मैंने विवरण को वापस एनम मान में बदलने के लिए एक रिवर्स एक्सटेंशन विधि बनाई:

public static T ToEnumValue<T>(this string enumerationDescription) where T : struct
{
    var type = typeof(T);

    if (!type.IsEnum)
        throw new ArgumentException("ToEnumValue<T>(): Must be of enum type", "T");

    foreach (object val in System.Enum.GetValues(type))
        if (val.GetDescription<T>() == enumerationDescription)
            return (T)val;

    throw new ArgumentException("ToEnumValue<T>(): Invalid description for enum " + type.Name, "enumerationDescription");
}

15
मुझे खेद है, लेकिन मददगार बनने की कोशिश करने के लिए धन्यवाद! यद्यपि यह एक प्रश्नोत्तर साइट है, इसलिए उत्तर सीधे प्रश्न का उत्तर देने का प्रयास होना चाहिए। और यह प्रश्न विशेष रूप से कहता है " मुझे स्ट्रिंग से मूल्य पर फिर से जाने में सक्षम होने की आवश्यकता नहीं है। " एक बार फिर, धन्यवाद!
जेसी

8
सकारात्मक आलोचना के लिए धन्यवाद। किसी साइट के लिए नया होना और उसकी संस्कृति और बारीकियों के बारे में सीखना हमेशा मुश्किल होता है। मुझे खुशी है कि आप जैसे लोग हैं जो नए लोगों को सीधे सेट करते हैं। एक बार फिर, नए आदमी पर डंपिंग नहीं करने के लिए धन्यवाद।
ब्रायन रिचर्डसन

6
@ जेसे और ४ साल बाद किसी को यहाँ ब्रीजकार्डसन कोड मिलने की खुशी है! SO एक प्रश्नोत्तर साइट हो सकती है, लेकिन इसका मतलब यह नहीं है कि सवालों के जवाब दिए जाने के बाद मृत हो जाते हैं।
जॉन

18

यहां सबसे आसान समाधान एक कस्टम एक्सटेंशन विधि (.NET 3.5 में कम से कम - का उपयोग करना है - आप इसे पहले के फ्रेमवर्क संस्करणों के लिए एक स्थिर सहायक विधि में बदल सकते हैं)।

public static string ToCustomString(this PublishStatusses value)
{
    switch(value)
    {
        // Return string depending on value.
    }
    return null;
}

मैं यहां यह मान रहा हूं कि आप एनम वैल्यू के वास्तविक नाम (जिसे आप केवल ToStone कॉल करके प्राप्त कर सकते हैं) के अलावा कुछ और लौटाना चाहते हैं।


यद्यपि मान्य है, मुझे विशेषता तरीका अधिक पसंद है। इस तरह मैं एक अलग पुस्तकालय में अपने toSTring विधि रख सकते हैं, जबकि खुद के साथ कस्टम स्ट्रिंग प्रतिनिधित्व डाल
बोरिस कॉल

1
काफी उचित। मुझे लगता है कि इस पद्धति का एक फायदा यह है कि आप कुछ राज्य चर को निर्दिष्ट करने की विधि के साथ एक तर्क शामिल कर सकते हैं, और फिर इस पर निर्भर करते हुए स्ट्रिंग प्रतिनिधित्व क्या लौटा सकते हैं।
नोल्डोरिन

1
हां, यह सब मेरे द्वारा अनुमान की गई विधि के दायरे पर निर्भर करता है। जबकि एट्रीब्यूट का तरीका अधिक सामान्य है, आपका समाधान अधिक स्थानीय है .. यह अंत में सभी जरूरतों के बारे में है।
बोरिस कॉल

1
आप अपनी इच्छानुसार विस्तार विधियाँ डाल सकते हैं। आपको बस इसे संदर्भित करना है जहां आप उनका उपयोग करना चाहते हैं।

हां, लेकिन इसका मतलब यह होगा कि हर बार जब आप एक नई एनम शुरू करते हैं, तो यह एक्स्टेंशन विधि फिर से लिखी जानी चाहिए। इसका मतलब यह भी होगा कि आपके सभी एप्लिकेशन आपके अन्य सभी अनुप्रयोगों के लिए अनुकूल नामों के आसपास ले जाएंगे ...
बोरिस कॉल

13

वह अन्य पोस्ट जावा है। आप Enums में C # में विधियाँ नहीं डाल सकते हैं।

बस कुछ इस तरह से करें:

PublishStatusses status = ...
String s = status.ToString();

यदि आप अपने enum मानों के लिए विभिन्न प्रदर्शन मानों का उपयोग करना चाहते हैं, तो आप Attributes and Reflection का उपयोग कर सकते हैं।


3
.String सभी मामलों में सुरक्षित नहीं है - एक ही मान के साथ कई प्रविष्टियों के साथ एक एनम (पूर्णांक एनम के लिए) पहले मिलान मूल्य की कुंजी लौटाएगा, न कि परीक्षण किए गए आइटम की कुंजी, यही कारण है कि Enum.GetName को पसंद किया जाता है
अन्नकूट

4
खैर यह उनकी विशिष्ट एनुम के लिए सबसे आसान समाधान था
लेमी

9

इस विस्तार वर्ग को अपनी परियोजना में शामिल करने का सबसे सरल तरीका है, यह परियोजना के किसी भी काम के साथ काम करेगा:

public static class EnumExtensions
{
    public static string ToFriendlyString(this Enum code)
    {
        return Enum.GetName(code.GetType(), code);
    }
}

उपयोग:

enum ExampleEnum
{
    Demo = 0,
    Test = 1, 
    Live = 2
}

...

ExampleEnum ee = ExampleEnum.Live;
Console.WriteLine(ee.ToFriendlyString());

2
यह रहस्य है कि इस टिप्पणी को स्वीकार क्यों नहीं किया गया, या सबसे अधिक उत्कीर्ण - कोई प्रतिबिंब नहीं, कोई अनावश्यक गुण नहीं, साधारण स्थितियों के लिए आदर्श जहां एनुम पहले से ही नामित है। आप इस उत्तर को एक कदम आगे ले जा सकते हैं और वापस लौटने से पहले 'माई एनम' में पूंजी अक्षरों के बीच रिक्त स्थान जोड़ने की अनुमति दे सकते हैं।
विक्स

12
यदि एनम पहले से ही नामांकित है, तो किसी भी विस्तार विधि की कोई आवश्यकता नहीं है। बस मौजूदा ToString () पद्धति का उपयोग करें। string result = "Result: " + ee;
जॉन

यह सबसे अच्छा जवाब होना चाहिए। यह किसी भी एनम के लिए काम करता है। तुम भी विशिष्ट Enum का उपयोग करके इसे लागू कर सकते हैं बस Enum प्रकार पैरामीटर के वास्तविक Enum जिस पर इसका उपयोग करने के लिए।
जुआन हाडो

6
यह उत्तर और सभी टिप्पणियां विस्तारित विवरण के लिए मूल अनुरोध को अनदेखा करती हैं। आप लोग पूरी तरह से अभ्यास से चूक गए हैं जो कि डिफ़ॉल्ट ToString मान के अलावा कुछ और वापस करना है। मैं यहाँ इस उत्तर के लिए सभी नोट्स को डाउनवोट नहीं करूँगा, लेकिन मुझे यकीन है कि मैं चाहता हूँ।
टोनीग

8

कुछ अन्य अधिक आदिम विकल्प जो कक्षाओं / संदर्भ प्रकारों से बचते हैं:

  • सरणी विधि
  • नेस्टेड स्ट्रक्चर मेथड

सरणी विधि

private struct PublishStatusses
{
    public static string[] Desc = {
        "Not Completed",
        "Completed",
        "Error"
    };

    public enum Id
    {
        NotCompleted = 0,
        Completed,
        Error
    };
}

प्रयोग

string desc = PublishStatusses.Desc[(int)PublishStatusses.Id.Completed];

नेस्टेड स्ट्रक्चर मेथड

private struct PublishStatusses
{
    public struct NotCompleted
    {
        public const int Id = 0;
        public const string Desc = "Not Completed";
    }

    public struct Completed
    {
        public const int Id = 1;
        public const string Desc = "Completed";
    }

    public struct Error
    {
        public const int Id = 2;
        public const string Desc = "Error";
    }            
}

प्रयोग

int id = PublishStatusses.NotCompleted.Id;
string desc = PublishStatusses.NotCompleted.Desc;

अपडेट (03/09/2018)

विस्तार विधियों का एक संकर और ऊपर की पहली तकनीक।

मैं परिभाषित करना पसंद करता हूं कि वे कहां हैं "वे" (मूल के अपने स्रोत के करीब हैं और कुछ सामान्य, वैश्विक नाम स्थान में नहीं)।

namespace ViewModels
{
    public class RecordVM
    {
        //public enum Enum { Minutes, Hours }
        public struct Enum
        {
            public enum Id { Minutes, Hours }
            public static string[] Name = { "Minute(s)", "Hour(s)" };
        }
    }
}

विस्तार विधि एक सामान्य क्षेत्र के लिए उपयुक्त लगती है, और एनम की "स्थानीयकृत" परिभाषा अब विस्तार विधि को और अधिक क्रियाशील बनाती है।

namespace Common
{
    public static class EnumExtensions
    {
        public static string Name(this RecordVM.Enum.Id id)
        {
            return RecordVM.Enum.Name[(int)id];
        }
    }   
}

एनम का एक उपयोग उदाहरण और यह विस्तार विधि है।

namespace Views
{
    public class RecordView 
    {
        private RecordDataFieldList<string, string> _fieldUnit;

        public RecordView()
        {
            _fieldUnit.List = new IdValueList<string, string>
            {            
                new ListItem<string>((int)RecordVM.Enum.Id.Minutes, RecordVM.Enum.Id.Minutes.Name()),
                new ListItem<string>((int)RecordVM.Enum.Id.Hours, RecordVM.Enum.Id.Hours.Name())
            };
        }

        private void Update()
        {    
            RecordVM.Enum.Id eId = DetermineUnit();

            _fieldUnit.Input.Text = _fieldUnit.List.SetSelected((int)eId).Value;
        }
    }
}

नोट: मैंने वास्तव में Enumरैपर (और Nameसरणी) को खत्म करने का फैसला किया , क्योंकि यह सबसे अच्छा है कि नाम स्ट्रिंग्स हार्ड कोडित होने के बजाय एक संसाधन (यानी कॉन्फिग फाइल या डीबी) से आते हैं, और क्योंकि मैंने एक्सटेंशन पद्धति को समाप्त कर दिया है ViewModelsनाम स्थान (बस एक अलग, "CommonVM.cs" फ़ाइल में)। साथ ही पूरी .Idचीज विचलित और बोझिल हो जाती है।

namespace ViewModels
{
    public class RecordVM
    {
        public enum Enum { Minutes, Hours }
        //public struct Enum
        //{
        //    public enum Id { Minutes, Hours }
        //    public static string[] Name = { "Minute(s)", "Hour(s)" };
        //}
    }
}

CommonVM.cs

//namespace Common
namespace ViewModels
{
    public static class EnumExtensions
    {
        public static string Name(this RecordVM.Enum id)
        {
            //return RecordVM.Enum.Name[(int)id];
            switch (id)
            {
                case RecordVM.Enum.Minutes: return "Minute(s)";                    
                case RecordVM.Enum.Hours: return "Hour(s)";
                default: return null;
            }
        }
    }   
}

एनम का एक उपयोग उदाहरण और यह विस्तार विधि है।

namespace Views
{
    public class RecordView 
    {
        private RecordDataFieldList<string, string> _fieldUnit

        public RecordView()
        {
            _fieldUnit.List = new IdValueList<string, string>
            {            
                new ListItem<string>((int)RecordVM.Enum.Id.Minutes, RecordVM.Enum.Id.Minutes.Name()),
                new ListItem<string>((int)RecordVM.Enum.Id.Hours, RecordVM.Enum.Id.Hours.Name())
            };
        }

        private void Update()
        {    
            RecordVM.Enum eId = DetermineUnit();

            _fieldUnit.Input.Text = _fieldUnit.List.SetSelected((int)eId).Value;
        }
    }
}

+ 1-1 = 0 वोट: यह समाधान Enum सिंटैक्स को संरक्षित करता है और बिना किसी प्रतिबिंब या जटिल कोड के समस्या को हल करता है, इसलिए +1 वहाँ। लेकिन यह खुद Enums की सुविधाओं को खो देता है। इसलिए जब IMO यह एक अच्छा विकल्प है, तो यह वास्तविक प्रश्न का उत्तर नहीं देता है और -1 प्राप्त करता है। नेट 0. क्षमा करें, हमारे पास एसओ में बेहतर रिकॉर्ड करने का कोई तरीका नहीं है।
टोनीग

@ टोनी मेला काफी Pluarlsight.com के .net स्किल असेसमेंट पर कुछ प्रश्नों के गुम होने के बाद मुझे एहसास होने लगा कि C # enum's में कितनी गहराई है, इसलिए यह संभव है कि कम से कम उनकी क्षमताओं को जानने से पहले एक अच्छा विचार है कि कौन सी कार्यप्रणाली को लागू करने से पहले (विशेष रूप से व्यापक उपयोग के लिए, रिफलेक्टरिंग) थोड़ा समय हो सकता है;)।
Samis

7

आप उपयोग कर सकते हैं Humanizer साथ पैकेज मानवीय Enums possiblity। एक बाज़:

enum PublishStatusses
{
    [Description("Custom description")]
    NotCompleted,
    AlmostCompleted,
    Error
};

तो आप Humanizeसीधे एनम पर विस्तार विधि का उपयोग कर सकते हैं :

var st1 = PublishStatusses.NotCompleted;
var str1 = st1.Humanize(); // will result in Custom description

var st2 = PublishStatusses.AlmostCompleted;
var str2 = st2.Humanize(); // will result in Almost completed (calculated automaticaly)

यह प्रतिबिंब का भी उपयोग करता है और कैश नहीं किया जाता है। github.com/Humanizr/Humanizer/blob/…
कोनराड

यह रे
कोनराड

5

रे बोयेसन के संबंध में, कोड में एक बग है: उपयोगकर्ता के अनुकूल तार के साथ Enum ToString

आपको एनम मूल्यों पर कई विशेषताओं के लिए खाते की आवश्यकता है।

public static string GetDescription<T>(this object enumerationValue)
            where T : struct
    {
        Type type = enumerationValue.GetType();
        if (!type.IsEnum)
        {
            throw new ArgumentException("EnumerationValue must be of Enum type", "enumerationValue");
        }

        //Tries to find a DescriptionAttribute for a potential friendly name
        //for the enum
        MemberInfo[] memberInfo = type.GetMember(enumerationValue.ToString());
        if (memberInfo != null && memberInfo.Length > 0)
        {
            object[] attrs = memberInfo[0].GetCustomAttributes(typeof(DescriptionAttribute), false);

            if (attrs != null && attrs.Length > 0 && attrs.Where(t => t.GetType() == typeof(DescriptionAttribute)).FirstOrDefault() != null)
            {
                //Pull out the description value
                return ((DescriptionAttribute)attrs.Where(t=>t.GetType() == typeof(DescriptionAttribute)).FirstOrDefault()).Description;
            }
        }
        //If we have no description attribute, just return the ToString of the enum
        return enumerationValue.ToString();

4
कई विवरण विशेषताओं के लिए एक चेक का चूक उद्देश्य पर है। यदि एनम के दो हैं, और आप एक विवरण उत्पन्न करने के लिए उपयोग कर रहे हैं, तो मुझे लगता है कि यह एक असाधारण परिस्थिति है। मुझे लगता है कि वास्तविक बग मैं एक एकल () एक अपवाद फेंकने के लिए नहीं है। अन्यथा पूरे विधि हस्ताक्षर का कोई मतलब नहीं है। GetDescription ()? कौन सा वर्णन? एक समुच्चय?
रे बोयसेन

4
public enum MyEnum
{
    [Description("Option One")]
    Option_One
}

public static string ToDescriptionString(this Enum This)
{
    Type type = This.GetType();

    string name = Enum.GetName(type, This);

    MemberInfo member = type.GetMembers()
        .Where(w => w.Name == name)
        .FirstOrDefault();

    DescriptionAttribute attribute = member != null
        ? member.GetCustomAttributes(true)
            .Where(w => w.GetType() == typeof(DescriptionAttribute))
            .FirstOrDefault() as DescriptionAttribute
        : null;

    return attribute != null ? attribute.Description : name;
}

3
हमेशा कुछ पाठ लिखना अच्छा होता है, जिसमें बताया गया है कि यह क्यों काम करना चाहिए और क्यों ओपी नहीं है।
फेयरस्ट

बस FYI, C # कोड कन्वेंशन लोकल वैरिएबल और विधि पैरामीटर्स को लोअर केस इनिशियल लेटर के साथ चाहते हैं। एक अपवाद thisविस्तार विधियों में पैरामीटर है, जिसे आप Thisवेब में कई उदाहरणों में देख सकते हैं । इसे अपने प्रकार की तरह कॉल करना जैसे आपने किया ( Enum Enum) कोड को कम पठनीय बनाते हैं।
मासिमिलियानो क्रूस

4

एनम का उपयोग करने के बजाय एक स्थिर वर्ग का उपयोग करें।

बदलने के

private enum PublishStatuses{
    NotCompleted,
    Completed,
    Error
};

साथ में

private static class PublishStatuses{
    public static readonly string NotCompleted = "Not Completed";
    public static readonly string Completed = "Completed";
    public static readonly string Error = "Error";
};

यह इस तरह से इस्तेमाल किया जाएगा

PublishStatuses.NotCompleted; // "Not Completed"

शीर्ष "एक्सटेंशन विधि" समाधान का उपयोग करके समस्या:

एक निजी एनम का उपयोग अक्सर दूसरे वर्ग के अंदर किया जाता है। विस्तार विधि समाधान वहाँ मान्य नहीं है क्योंकि यह अपने वर्ग में होना चाहिए। यह समाधान निजी हो सकता है और किसी अन्य वर्ग में एम्बेड किया जा सकता है।


2

मैं एक VB.NET प्रशंसक हो सकता हूं, इसलिए यहां मेरा संस्करण, एक्सटेंशन विधि के साथ विवरणएट्रिब्यूट विधि का संयोजन है। सबसे पहले, परिणाम:

Imports System.ComponentModel ' For <Description>

Module Module1
  ''' <summary>
  ''' An Enum type with three values and descriptions
  ''' </summary>
  Public Enum EnumType
    <Description("One")>
    V1 = 1

    ' This one has no description
    V2 = 2

    <Description("Three")>
    V3 = 3
  End Enum

  Sub Main()
    ' Description method is an extension in EnumExtensions
    For Each v As EnumType In [Enum].GetValues(GetType(EnumType))
      Console.WriteLine("Enum {0} has value {1} and description {2}",
        v,
        CInt(v),
        v.Description
      )
    Next
    ' Output:
    ' Enum V1 has value 1 and description One
    ' Enum V2 has value 2 and description V2
    ' Enum V3 has value 3 and description Three
  End Sub
End Module

मूल सामग्री: तीन मूल्यों V1, V2 और V3 के साथ EnumType नामक एक एनम। "मैजिक" कंसोल में होता है। सब मेन () में लाइटलाइन कॉल, जहां अंतिम तर्क बस है v.Description। यह V1 के लिए "वन", V2 के लिए "V2" और V3 के लिए "तीन" देता है। यह विवरण-विधि वास्तव में एक विस्तार विधि है, जिसे EnumExtensions नामक एक अन्य मॉड्यूल में परिभाषित किया गया है:

Option Strict On
Option Explicit On
Option Infer Off

Imports System.Runtime.CompilerServices
Imports System.Reflection
Imports System.ComponentModel

Module EnumExtensions
  Private _Descriptions As New Dictionary(Of String, String)

  ''' <summary>
  ''' This extension method adds a Description method
  ''' to all enum members. The result of the method is the
  ''' value of the Description attribute if present, else
  ''' the normal ToString() representation of the enum value.
  ''' </summary>
  <Extension>
  Public Function Description(e As [Enum]) As String
    ' Get the type of the enum
    Dim enumType As Type = e.GetType()
    ' Get the name of the enum value
    Dim name As String = e.ToString()

    ' Construct a full name for this enum value
    Dim fullName As String = enumType.FullName + "." + name

    ' See if we have looked it up earlier
    Dim enumDescription As String = Nothing
    If _Descriptions.TryGetValue(fullName, enumDescription) Then
      ' Yes we have - return previous value
      Return enumDescription
    End If

    ' Find the value of the Description attribute on this enum value
    Dim members As MemberInfo() = enumType.GetMember(name)
    If members IsNot Nothing AndAlso members.Length > 0 Then
      Dim descriptions() As Object = members(0).GetCustomAttributes(GetType(DescriptionAttribute), False)
      If descriptions IsNot Nothing AndAlso descriptions.Length > 0 Then
        ' Set name to description found
        name = DirectCast(descriptions(0), DescriptionAttribute).Description
      End If
    End If

    ' Save the name in the dictionary:
    _Descriptions.Add(fullName, name)

    ' Return the name
    Return name
  End Function
End Module

क्योंकि वर्णन विशेषताओं का उपयोग Reflectionकरना धीमा है, इसलिए लुकअप को एक निजी में भी कैश किया गया हैDictionary , जो कि मांग पर पॉप्युलेट होता है।

(VB.NET समाधान के लिए क्षमा करें - इसे C # में अनुवाद करने के लिए अपेक्षाकृत अधिक स्ट्रिफ़ोरवर्ड होना चाहिए, और मेरा C # एक्सटेंशन जैसे नए विषयों पर कठोर है)


2

नमूने के साथ उपरोक्त सुझावों का स्वच्छ सारांश:

namespace EnumExtensions {

using System;
using System.Reflection;

public class TextAttribute : Attribute {
   public string Text;
   public TextAttribute( string text ) {
      Text = text;
   }//ctor
}// class TextAttribute

public static class EnumExtender {

public static string ToText( this Enum enumeration ) {

   MemberInfo[] memberInfo = enumeration.GetType().GetMember( enumeration.ToString() );

   if ( memberInfo != null && memberInfo.Length > 0 ) {

      object[] attributes = memberInfo[ 0 ].GetCustomAttributes( typeof(TextAttribute),  false );

      if ( attributes != null && attributes.Length > 0 ) {
         return ( (TextAttribute)attributes[ 0 ] ).Text;
      }

   }//if

   return enumeration.ToString();

}//ToText

}//class EnumExtender

}//namespace

उपयोग:

using System;
using EnumExtensions;

class Program {

public enum Appearance {

  [Text( "left-handed" ) ]
  Left,

  [Text( "right-handed" ) ]
  Right,

}//enum

static void Main( string[] args ) {

   var appearance = Appearance.Left;
   Console.WriteLine( appearance.ToText() );

}//Main

}//class

1
सी # में एक [विवरण ("")] विशेषता है, इसका उपयोग क्यों नहीं किया जाता है?
स्टीफन कोएनन

बेशक [विवरण ("")] का उपयोग करना एक रास्ता है। लेकिन मैं चाहता था कि नमूना पूरा हो।
अंडरस्कोर

2

Enum.GetName का उपयोग करें

उपरोक्त लिंक से ...

using System;

public class GetNameTest {
    enum Colors { Red, Green, Blue, Yellow };
    enum Styles { Plaid, Striped, Tartan, Corduroy };

    public static void Main() {

        Console.WriteLine("The 4th value of the Colors Enum is {0}", Enum.GetName(typeof(Colors), 3));
        Console.WriteLine("The 4th value of the Styles Enum is {0}", Enum.GetName(typeof(Styles), 3));
    }
}
// The example displays the following output:
//       The 4th value of the Colors Enum is Yellow
//       The 4th value of the Styles Enum is Corduroy

2

इस दस्तावेज के अनुसार: https://docs.microsoft.com/pt-br/dotnet/api/system.enum.tostring?view=netframework-4.8

इस तरह एक प्रारूप का उपयोग करके किसी एन्यूमरेटर को स्ट्रिंग में परिवर्तित करना संभव है:

public enum Example
{
    Example1,
    Example2
}

Console.WriteLine(Example.Example1.ToString("g"));

//Outputs: "Example1"

आप इस लिंक में सभी संभावित प्रारूप देख सकते हैं: https://docs.microsoft.com/pt-br/dotnet/api/system.string?view=netframework-4.8


1

यह Ray Booysen के कोड के लिए एक अपडेट है जो सामान्य गेटकॉन्स्टट्यूएंट विधि और LINQ का उपयोग करता है ताकि चीजें थोड़ा सा बन सकें।

    /// <summary>
    /// Gets the value of the <see cref="T:System.ComponentModel.DescriptionAttribute"/> on an struct, including enums.  
    /// </summary>
    /// <typeparam name="T">The type of the struct.</typeparam>
    /// <param name="enumerationValue">A value of type <see cref="T:System.Enum"/></param>
    /// <returns>If the struct has a Description attribute, this method returns the description.  Otherwise it just calls ToString() on the struct.</returns>
    /// <remarks>Based on http://stackoverflow.com/questions/479410/enum-tostring/479417#479417, but useful for any struct.</remarks>
    public static string GetDescription<T>(this T enumerationValue) where T : struct
    {
        return enumerationValue.GetType().GetMember(enumerationValue.ToString())
                .SelectMany(mi => mi.GetCustomAttributes<DescriptionAttribute>(false),
                    (mi, ca) => ca.Description)
                .FirstOrDefault() ?? enumerationValue.ToString();
    }   

यह देखने में असफल है कि आपको सामान्य होने की आवश्यकता क्यों है? यदि आप प्रतिबिंब का उपयोग करने जा रहे हैं?
ली लौविएरे

@LeeLouviere मुख्य रूप से बॉक्सिंग से बचने के लिए जब संरचना (मान प्रकार) को एक पैरामीटर के रूप में पारित किया जाता है।
रिचर्ड एंथनी हेन

1
इसके बजाय numerationValue.GetType () उपयोग: टाइपोफ (टी)।
स्लाव

1
पठनीयता खोने के बिना (YMMV) स्वीकार किए गए उत्तर पर एकतरफा सुधार करना। हां, टाइपोफ (टी) के साथ।
टोनीजी

1

यहां तक ​​कि क्लीनर सारांश:

using System;
using System.Reflection;

public class TextAttribute : Attribute
{
    public string Text;
    public TextAttribute(string text)
    {
        Text = text;
    }
}  

public static class EnumExtender
{
    public static string ToText(this Enum enumeration)
    {
        var memberInfo = enumeration.GetType().GetMember(enumeration.ToString());
        if (memberInfo.Length <= 0) return enumeration.ToString();

        var attributes = memberInfo[0].GetCustomAttributes(typeof(TextAttribute), false);
        return attributes.Length > 0 ? ((TextAttribute)attributes[0]).Text : enumeration.ToString();
    }
}

अंडरस्कोर के समान उपयोग का वर्णन है।


0

सहित झंडे के लिए।

    public static string Description(this Enum value)
    {
        Type type = value.GetType();

        List<string> res = new List<string>();
        var arrValue = value.ToString().Split(',').Select(v=>v.Trim());
        foreach (string strValue in arrValue)
        {
            MemberInfo[] memberInfo = type.GetMember(strValue);
            if (memberInfo != null && memberInfo.Length > 0)
            {
                object[] attrs = memberInfo[0].GetCustomAttributes(typeof(DescriptionAttribute), false);

                if (attrs != null && attrs.Length > 0 && attrs.Where(t => t.GetType() == typeof(DescriptionAttribute)).FirstOrDefault() != null)
                {
                    res.Add(((DescriptionAttribute)attrs.Where(t => t.GetType() == typeof(DescriptionAttribute)).FirstOrDefault()).Description);
                }
                else
                    res.Add(strValue);
            }
            else
                res.Add(strValue);
        }

        return res.Aggregate((s,v)=>s+", "+v);
    }

0

यदि आप केवल शब्दों के बीच एक व्हाट्सएप जोड़ना चाहते हैं, तो यह उतना ही सरल है

string res = Regex.Replace(PublishStatusses.NotCompleted, "[A-Z]", " $0").Trim();

0

मैं विवरण प्राप्त करने के लिए एनम / विवरण जोड़े और एक नेस्टेड सहायक वर्ग को संग्रहीत करने के लिए एक सामान्य वर्ग का उपयोग करता हूं।

enum :

enum Status { Success, Fail, Pending }

सामान्य वर्ग:

नोट: चूँकि एक सामान्य वर्ग को एक एनम द्वारा बाध्य नहीं किया जा सकता है, इसलिए मैं इसके बजाय संरचना द्वारा विवश हूँ और निर्माणकर्ता में एनम के लिए जाँच कर रहा हूँ ।

public class EnumX<T> where T : struct
{
    public T Code { get; set; }
    public string Description { get; set; }

    public EnumX(T code, string desc)
    {
        if (!typeof(T).IsEnum) throw new NotImplementedException();

        Code = code;
        Description = desc;
    }

    public class Helper
    {
        private List<EnumX<T>> codes;

        public Helper(List<EnumX<T>> codes)
        {
            this.codes = codes;
        }

        public string GetDescription(T code)
        {
            EnumX<T> e = codes.Where(c => c.Code.Equals(code)).FirstOrDefault();
            return e is null ? "Undefined" : e.Description;
        }
    }
}

उपयोग:

EnumX<Status>.Helper StatusCodes = new EnumX<Status>.Helper(new List<EnumX<Status>>()
        {
            new EnumX<Status>(Status.Success,"Operation was successful"),
            new EnumX<Status>(Status.Fail,"Operation failed"),
            new EnumX<Status>(Status.Pending,"Operation not complete. Please wait...")
        });

        Console.WriteLine(StatusCodes.GetDescription(Status.Pending));

-2

मुझे लगता है कि आपकी समस्या को हल करने का सबसे अच्छा (और सबसे आसान) तरीका है कि आप अपने एनम के लिए एक्सटेंशन-मेथड लिखें:

public static string GetUserFriendlyString(this PublishStatusses status)
    {

    }

1
7 साल पहले किसी ने कहा था कि
स्टीवन

-3

यदि आप पूरी तरह से अनुकूलन चाहते हैं, तो यहां मेरे समाधान का प्रयास करें:

http://www.kevinwilliampang.com/post/Mapping-Enums-To-Strings-and-Strings-to-Enums-in-NET.aspx

मूल रूप से, पोस्ट बताती है कि अपने प्रत्येक एनम के विवरणों को कैसे संलग्न किया जाए और एनम से वर्णन करने के लिए मैप करने के लिए एक सामान्य तरीका प्रदान करता है।


1
और अब साइट डाउन है।
निक फोस्टर
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.