एक Enum का स्ट्रिंग प्रतिनिधित्व


911

मेरे पास निम्नलिखित गणना है:

public enum AuthenticationMethod
{
    FORMS = 1,
    WINDOWSAUTHENTICATION = 2,
    SINGLESIGNON = 3
}

समस्या यह है कि जब मुझे AuthenticationMethod.FORMS के लिए और आईडी 1 के लिए पूछें तो मुझे "FORMS" शब्द की आवश्यकता है।

मैंने इस समस्या के लिए निम्नलिखित समाधान पाया है ( लिंक) ):

पहले मुझे "StringValue" नामक एक कस्टम विशेषता बनाने की आवश्यकता है:

public class StringValue : System.Attribute
{
    private readonly string _value;

    public StringValue(string value)
    {
        _value = value;
    }

    public string Value
    {
        get { return _value; }
    }

}

फिर मैं इस विशेषता को अपने एन्यूमरेटर में जोड़ सकता हूं:

public enum AuthenticationMethod
{
    [StringValue("FORMS")]
    FORMS = 1,
    [StringValue("WINDOWS")]
    WINDOWSAUTHENTICATION = 2,
    [StringValue("SSO")]
    SINGLESIGNON = 3
}

और निश्चित रूप से मुझे उस StringValue को पुनः प्राप्त करने के लिए कुछ चाहिए:

public static class StringEnum
{
    public static string GetStringValue(Enum value)
    {
        string output = null;
        Type type = value.GetType();

        //Check first in our cached results...

        //Look for our 'StringValueAttribute' 

        //in the field's custom attributes

        FieldInfo fi = type.GetField(value.ToString());
        StringValue[] attrs =
           fi.GetCustomAttributes(typeof(StringValue),
                                   false) as StringValue[];
        if (attrs.Length > 0)
        {
            output = attrs[0].Value;
        }

        return output;
    }
}

अच्छा अब मुझे एक एन्यूमरेटर के लिए एक स्ट्रिंग मान प्राप्त करने के लिए उपकरण मिल गए हैं। मैं तो इसे इस तरह उपयोग कर सकते हैं:

string valueOfAuthenticationMethod = StringEnum.GetStringValue(AuthenticationMethod.FORMS);

ठीक है अब ये सभी एक आकर्षण की तरह काम करते हैं लेकिन मुझे यह पूरी तरह से काम लगता है। मैं सोच रहा था कि क्या इसके लिए कोई बेहतर उपाय है।

मैंने एक शब्दकोश और स्थिर गुणों के साथ कुछ करने की कोशिश की, लेकिन यह बेहतर नहीं था।


8
अच्छा! मैं इसका उपयोग स्थानीयकृत तारों के लिए enum मानों का अनुवाद करने के लिए कर सकता हूं।
9yvind Skaar

5
हालांकि आपको यह लंबे समय तक घुमावदार लग सकता है, लेकिन यह वास्तव में अन्य चीजों के लिए बहुत ही लचीला तरीका है। जैसा कि मेरे एक सहकर्मी ने बताया, इसका उपयोग कई मामलों में Enum Helpers को बदलने के लिए किया जा सकता है जो डेटाबेस कोड्स को मानों को मानने के लिए मैप करते हैं ...
BenAlabaster

27
"एट्रीब्यूट" प्रत्यय के साथ MSDN reccoments प्रत्यय विशेषता वर्ग। तो "क्लास स्ट्रिंगरवेल्यू एट्रिब्यूट";)
सर्हियो

14
मैं @BenAlabaster से सहमत हूं यह वास्तव में काफी लचीला है। इसके अलावा, आप इसे अपनी स्टैटिक विधि के thisसामने जोड़कर एक विस्तार विधि बना सकते हैं Enum। फिर आप कर सकते हैं AuthenticationMethod.Forms.GetStringValue();
जस्टिन पिहोनी

5
यह दृष्टिकोण विशेषता मानों को पढ़ने के लिए प्रतिबिंब का उपयोग करता है और यह बहुत धीमा है यदि आपको मेरे अनुभव में कई बार GetStringValue () कॉल करना पड़ता है। टाइप-सेफ-एनम पैटर्न अधिक तेज है।
2222 पर Rn222

जवाबों:


868

टाइप-सेफ-एनम पैटर्न की कोशिश करें ।

public sealed class AuthenticationMethod {

    private readonly String name;
    private readonly int value;

    public static readonly AuthenticationMethod FORMS = new AuthenticationMethod (1, "FORMS");
    public static readonly AuthenticationMethod WINDOWSAUTHENTICATION = new AuthenticationMethod (2, "WINDOWS");
    public static readonly AuthenticationMethod SINGLESIGNON = new AuthenticationMethod (3, "SSN");        

    private AuthenticationMethod(int value, String name){
        this.name = name;
        this.value = value;
    }

    public override String ToString(){
        return name;
    }

}

अपडेट स्पष्ट (या निहित) प्रकार रूपांतरण द्वारा किया जा सकता है

  • मानचित्रण के साथ स्थिर क्षेत्र जोड़ना

    private static readonly Dictionary<string, AuthenticationMethod> instance = new Dictionary<string,AuthenticationMethod>();
    • nb आदेश में कि "एनम सदस्य" फ़ील्ड का आरंभीकरण एक NullReferenceException को नहीं फेंकता है जब इंस्टेंस कंस्ट्रक्टर को कॉल किया जाता है, तो अपनी कक्षा में "एनम सदस्य" फ़ील्ड से पहले शब्दकोश फ़ील्ड को रखना सुनिश्चित करें। ऐसा इसलिए है क्योंकि स्थैतिक क्षेत्र के शुरुआती लोगों को घोषणा के क्रम में कहा जाता है, और स्थैतिक निर्माता से पहले, अजीब और आवश्यक लेकिन भ्रामक स्थिति पैदा कर रहा है कि उदाहरण के निर्माणकर्ता को सभी स्थिर क्षेत्रों को आरंभीकृत करने से पहले बुलाया जा सकता है, और इससे पहले कि स्थैतिक निर्माता को बुलाया जाए।
  • उदाहरण के निर्माण में इस मानचित्रण को भरना

    instance[name] = this;
  • और उपयोगकर्ता-परिभाषित प्रकार रूपांतरण ऑपरेटर को जोड़ना

    public static explicit operator AuthenticationMethod(string str)
    {
        AuthenticationMethod result;
        if (instance.TryGetValue(str, out result))
            return result;
        else
            throw new InvalidCastException();
    }

17
यह एक एनम की तरह दिखता है, लेकिन यह एक एनम नहीं है। मैं कल्पना कर सकता हूं कि अगर लोगों ने AuthenticationMethods की तुलना करने की कोशिश शुरू कर दी तो कुछ दिलचस्प समस्याएं पैदा हो सकती हैं। आपको शायद विभिन्न समानता ऑपरेटरों को भी अधिभारित करने की आवश्यकता है।
चींटी

36
@ नहीं: मेरे पास नहीं है। चूँकि हमारे पास प्रत्येक AuthenticationMethod का केवल एक ही उदाहरण है, ऑब्जेक्ट ऑब्जेक्ट से ली गई संदर्भ समानता ठीक है।
जैकब atturc

10
@tyriker: कंपाइलर करता है। कंस्ट्रक्टर निजी है, इसलिए आप नए उदाहरण नहीं बना सकते हैं। इसके अलावा स्थिर सदस्य उदाहरण के माध्यम से सुलभ नहीं हैं।
जैकब cturc

21
@ जाकुब बहुत दिलचस्प। मुझे इसका उपयोग करने के तरीके का पता लगाने के लिए इसके साथ खेलना था, और इसके लाभों का एहसास करना था। यह एक सार्वजनिक, गैर-स्थिर वर्ग है, लेकिन इसे तत्काल नहीं किया जा सकता है और आप केवल इसके स्थिर सदस्यों तक ही पहुँच सकते हैं। मूल रूप से, यह एक एनम की तरह व्यवहार करता है। लेकिन सबसे अच्छा हिस्सा ... स्थिर सदस्य वर्ग के टाइप किए जाते हैं न कि सामान्य स्ट्रिंग या इंट। यह एक ... [इसके लिए प्रतीक्षा करें] ... सुरक्षित एनम टाइप करें! मुझे समझने में मदद करने के लिए धन्यवाद।
tyriker

6
@ मिर्कान ने नीचे जकूब cturc के उत्तर का थोड़ा संशोधित संस्करण पोस्ट किया है जो इसे स्विच-केस स्टेटमेंट के साथ उपयोग करने की अनुमति देता है, इसलिए अब इस दृष्टिकोण के लिए कोई नकारात्मक पहलू नहीं है :)
deadlydog

228

प्रयोग विधि

Enum.GetName(Type MyEnumType,  object enumvariable)  

के रूप में (मान लें Shipperएक परिभाषित Enum है)

Shipper x = Shipper.FederalExpress;
string s = Enum.GetName(typeof(Shipper), x);

Enum वर्ग पर अन्य स्थिर तरीकों का एक समूह भी जांच के लायक है ...


5
बिल्कुल सही। मैंने एक स्ट्रिंग विवरण के लिए एक कस्टम विशेषता बनाई थी, लेकिन ऐसा इसलिए है क्योंकि मैं एक उपयोगकर्ता के अनुकूल संस्करण (रिक्त स्थान और अन्य विशेष वर्णों के साथ) चाहता हूं जो आसानी से कॉम्बो बॉक्स या इस तरह से बंधे हो सकते हैं।
एलसी।

5
Enum.GetName एनम में फ़ील्ड नामों को दर्शाता है - .ToString () के समान। यदि प्रदर्शन एक मुद्दा है तो यह एक समस्या हो सकती है। मैं इसके बारे में तब तक चिंता नहीं करूंगा, जब तक आप एनम के भार को परिवर्तित नहीं कर रहे हैं।
कीथ

8
एक अन्य विकल्प पर विचार करने के लिए, यदि आपको अतिरिक्त फंक्शनलिटी के साथ एक एनम की आवश्यकता है, तो एक स्ट्रक्चर का उपयोग करके "रोल यार ओन" करना है ... यदि आप स्ट्रक्चर के अलग-अलग इंस्टेंस उत्पन्न करने वाले कंस्ट्रक्टरों के लिए आरम्भ किए गए एनम वैल्यूज को दर्शाने के लिए स्टैटिक रीडोनॉली नाम गुणों को जोड़ते हैं। ...
चार्ल्स ब्रेटाना

1
फिर आप जो भी अन्य संरचनात्मक सदस्यों को जोड़ सकते हैं, जो भी कार्यक्षमता आप इस "एनम" को लागू करना चाहते हैं, को लागू करने के लिए ...
चार्ल्स ब्रेटाना

2
यहाँ मुद्दा यह है कि GetName स्थानीय नहीं है। यह हमेशा एक चिंता का विषय नहीं है, लेकिन इसके बारे में जागरूक होना कुछ है।
योएल कोएहॉर्न

79

आप ToString () का उपयोग करके मान के बजाय नाम का संदर्भ दे सकते हैं

Console.WriteLine("Auth method: {0}", AuthenticationMethod.Forms.ToString());

प्रलेखन यहाँ है:

http://msdn.microsoft.com/en-us/library/16c1xs4z.aspx

... और यदि आप पास्कल केस में अपने एनम का नाम रखते हैं (जैसा कि मैं करता हूं - जैसे कि ThisIsMyEnumValue = 1 आदि) तो आप दोस्ताना फॉर्म को प्रिंट करने के लिए एक बहुत ही सरल रेगेक्स का उपयोग कर सकते हैं:

static string ToFriendlyCase(this string EnumString)
{
    return Regex.Replace(EnumString, "(?!^)([A-Z])", " $1");
}

जिसे आसानी से किसी भी तार से बुलाया जा सकता है:

Console.WriteLine("ConvertMyCrazyPascalCaseSentenceToFriendlyCase".ToFriendlyCase());

आउटपुट:

मेरे पागल पास्कल मामले की सजा को फ्रेंडली केस में परिवर्तित करें

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

मैं आपके मूल समाधान को पसंद करता हूं, हालांकि अधिक जटिल परिदृश्यों के लिए। आप अपने समाधान को एक कदम आगे ले जा सकते हैं और अपने GetStringValue को अपने एनम का विस्तार विधि बना सकते हैं और फिर आपको इसे StringEnum.GetStringValue की तरह संदर्भित करने की आवश्यकता नहीं होगी ...

public static string GetStringValue(this AuthenticationMethod value)
{
  string output = null;
  Type type = value.GetType();
  FieldInfo fi = type.GetField(value.ToString());
  StringValue[] attrs = fi.GetCustomAttributes(typeof(StringValue), false) as StringValue[];
  if (attrs.Length > 0)
    output = attrs[0].Value;
  return output;
}

तब आप इसे आसानी से सीधे अपने enum उदाहरण से एक्सेस कर सकते हैं:

Console.WriteLine(AuthenticationMethod.SSO.GetStringValue());

2
यह मदद नहीं करता है अगर "दोस्ताना नाम" को एक स्थान की आवश्यकता है। जैसे "फॉर्म ऑथेंटिकेशन"
रे बोयसेन

4
तो सुनिश्चित करें कि एनुम को फॉर्मसुथेंटिकेशन जैसे कैप के साथ नामित किया गया है और शुरुआत में किसी भी कैप से पहले एक जगह डालें। यह रॉकेट साइंस नहीं है कि एक स्ट्रिंग में जगह डालें ...
BenAlabaster

4
पास्कल केस के नामों की ऑटो-स्पेसिंग समस्याग्रस्त हो जाती है यदि उनमें ऐसे संक्षिप्तीकरण होते हैं जिन्हें उदाहरण के लिए कैपिटल, XML या GPS होना चाहिए।
रिचर्ड ईव

2
@RichardEv, इसके लिए कोई परफेक्ट रेगेक्स नहीं है, लेकिन यहाँ एक है जो संक्षिप्त के साथ थोड़ा बेहतर काम करना चाहिए। "(?!^)([^A-Z])([A-Z])", "$1 $2"। तो HereIsATESTबन जाता है Here Is ATEST
स्पेयरबाइट्स

नहीं इन छोटे "हैक" कर रहा है जो वे कर रहे हैं। मुझे वही मिलता है जो ओपी कह रहा है और मैं एक समान समाधान खोजने की कोशिश कर रहा हूं अर्थात Enums की शान का उपयोग कर रहा हूं लेकिन संबंधित संदेश को आसानी से उपयोग करने में सक्षम है। केवल समाधान मैं सोच सकता हूं कि एनम नाम और स्ट्रिंग मान के बीच किसी प्रकार का मानचित्रण लागू करना है, लेकिन यह स्ट्रिंग डेटा को बनाए रखने के मुद्दे पर नहीं घेरता है (हालांकि यह उन परिदृश्यों के लिए व्यावहारिक बनाता है जहां आपको बहु क्षेत्रों आदि की आवश्यकता होती है। )
ताहिर खालिद

72

दुर्भाग्य से enums पर विशेषताओं को पाने के लिए प्रतिबिंब काफी धीमा है:

इस प्रश्न को देखें: कोई भी एक एनुम मूल्य पर कस्टम विशेषताओं को प्राप्त करने का एक त्वरित तरीका जानता है?

.ToString()भी enums पर काफी धीमी है।

यद्यपि आप एनमों के लिए विस्तार विधि लिख सकते हैं:

public static string GetName( this MyEnum input ) {
    switch ( input ) {
        case MyEnum.WINDOWSAUTHENTICATION:
            return "Windows";
        //and so on
    }
}

यह महान नहीं है, लेकिन त्वरित होगा और विशेषताओं या फ़ील्ड नाम के लिए प्रतिबिंब की आवश्यकता नहीं होगी।


C # 6 अपडेट

यदि आप C # 6 का उपयोग कर सकते हैं तो नया nameofऑपरेटर एनम के लिए काम करता है, इसलिए संकलन समय पर nameof(MyEnum.WINDOWSAUTHENTICATION)परिवर्तित हो जाएगा , जिससे एनम नाम प्राप्त करने का सबसे तेज़ तरीका हो जाएगा।"WINDOWSAUTHENTICATION"

ध्यान दें कि यह स्पष्ट एनम को एक इनबिल्ट कॉन्स्टैंट में बदल देगा, इसलिए यह उन एनमों के लिए काम नहीं करता है जो आपके पास एक वैरिएबल में हैं। इसलिए:

nameof(AuthenticationMethod.FORMS) == "FORMS"

परंतु...

var myMethod = AuthenticationMethod.FORMS;
nameof(myMethod) == "myMethod"

24
आप एक बार विशेषता मान प्राप्त कर सकते हैं और उन्हें घोषणात्मक पहलू रखने के लिए एक शब्दकोश <MyEnum, string> में डाल सकते हैं।
जॉन स्कीट

1
हाँ, यही कि हमने बहुत सारी दुश्मनी वाले ऐप में काम किया, जब हमें पता चला कि प्रतिबिंब बोतल-गर्दन का था।
कीथ

धन्यवाद जॉन और कीथ, मैं आपके शब्दकोश सुझाव का उपयोग करके समाप्त हुआ। महान (और तेज़!) काम करता है।
हेलिज क्लेन

@JonSkeet मुझे पता है कि यह पुराना है। लेकिन कोई इसे कैसे हासिल करेगा?
user919426

2
@ user919426: प्राप्त करना चाहते हैं? उन्हें एक शब्दकोष में रखना? बस एक शब्दकोश बनाएं, आदर्श रूप से एक संग्रह आरंभीकरण के साथ ... यह स्पष्ट नहीं है कि आप क्या पूछ रहे हैं।
जॉन स्कीट

59

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

public static class AttributesHelperExtension
    {
        public static string ToDescription(this Enum value)
        {
            var da = (DescriptionAttribute[])(value.GetType().GetField(value.ToString())).GetCustomAttributes(typeof(DescriptionAttribute), false);
            return da.Length > 0 ? da[0].Description : value.ToString();
        }
}

अब के enumसाथ सजाने :

public enum AuthenticationMethod
{
    [Description("FORMS")]
    FORMS = 1,
    [Description("WINDOWSAUTHENTICATION")]
    WINDOWSAUTHENTICATION = 2,
    [Description("SINGLESIGNON ")]
    SINGLESIGNON = 3
}

जब तुमने फोन किया

AuthenticationMethod.FORMS.ToDescription()आपको मिलेगा "FORMS"


1
मुझे using System.ComponentModel;यह भी जोड़ना था , यह विधि केवल तभी काम करती है जब आप चाहते हैं कि स्ट्रिंग मान Enum के नाम के समान हो। ओपी एक अलग मूल्य चाहता था।
एल्कूल

2
जब आप फोन करते हैं तो क्या आपका मतलब नहीं है AuthenticationMethod.FORMS.ToDescription()?
निकोडेमस 13

41

बस ToString()विधि का उपयोग करें

public enum any{Tomato=0,Melon,Watermelon}

स्ट्रिंग को संदर्भित करने के लिए Tomato, बस उपयोग करें

any.Tomato.ToString();

वाह। वह तो आसान था। मुझे पता है कि ओपी कस्टम स्ट्रिंग विवरण जोड़ना चाहते थे, लेकिन मुझे यही चाहिए। मुझे यह पता लगाने की कोशिश करनी चाहिए, पूर्वव्यापी में, लेकिन मैं Enum.GetName मार्ग से नीचे चला गया।
रिफ़े

7
क्यों हर किसी को यह अधिक जटिल है?
ब्रेंट

18
@ बेंट क्योंकि सबसे अधिक बार आपके पास .ToString()उपयोगकर्ता के अनुकूल मूल्य की तुलना में भिन्न मूल्य होता है।
Novitchi S

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

1
@ होगन - टूस्ट्रिंग () चर पर भी काम करता है: any fruit = any.Tomato; string tomato = fruit.ToString();
LiborV

29

.Net 4.0 और इसके बाद के संस्करण के लिए इसका बहुत ही सरल समाधान है। किसी अन्य कोड की आवश्यकता नहीं है।

public enum MyStatus
{
    Active = 1,
    Archived = 2
}

केवल उपयोग के बारे में स्ट्रिंग प्राप्त करने के लिए:

MyStatus.Active.ToString("f");

या

MyStatus.Archived.ToString("f");`

मान "सक्रिय" या "संग्रहीत" होगा।

कॉल करने पर विभिन्न स्ट्रिंग फॉर्मेट (ऊपर से "f") Enum.ToStringदेखने के लिए इस एन्यूमरेशन फॉर्मेट स्ट्रिंग्स पेज को देखें


28

मैं System.ComponentModel नाम स्थान से विवरण विशेषता का उपयोग करता हूं। बस एनम को सजाने और फिर इसे प्राप्त करने के लिए इस कोड का उपयोग करें:

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)
                {
                    //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();

        }

उदहारण के लिए:

public enum Cycle : int
{        
   [Description("Daily Cycle")]
   Daily = 1,
   Weekly,
   Monthly
}

यह कोड अच्छी तरह से उन Enums के लिए पूरा करता है जहाँ आपको "दोस्ताना नाम" की आवश्यकता नहीं होती है और यह enum के सिर्फ .ToString () में वापस आ जाएगा।


27

मुझे वास्तव में जैकब urturc का उत्तर पसंद है, लेकिन यह कमी है कि आप इसे स्विच-केस स्टेटमेंट के साथ उपयोग नहीं कर सकते। यहां उनके उत्तर का थोड़ा संशोधित संस्करण है जिसे स्विच स्टेटमेंट के साथ प्रयोग किया जा सकता है:

public sealed class AuthenticationMethod
{
    #region This code never needs to change.
    private readonly string _name;
    public readonly Values Value;

    private AuthenticationMethod(Values value, String name){
        this._name = name;
        this.Value = value;
    }

    public override String ToString(){
        return _name;
    }
    #endregion

    public enum Values
    {
        Forms = 1,
        Windows = 2,
        SSN = 3
    }

    public static readonly AuthenticationMethod FORMS = new AuthenticationMethod (Values.Forms, "FORMS");
    public static readonly AuthenticationMethod WINDOWSAUTHENTICATION = new AuthenticationMethod (Values.Windows, "WINDOWS");
    public static readonly AuthenticationMethod SINGLESIGNON = new AuthenticationMethod (Values.SSN, "SSN");
}

तो आपको जकुब cturc के उत्तर के सभी लाभ मिलते हैं, साथ ही हम इसका उपयोग स्विच स्टेटमेंट के साथ कर सकते हैं:

var authenticationMethodVariable = AuthenticationMethod.FORMS;  // Set the "enum" value we want to use.
var methodName = authenticationMethodVariable.ToString();       // Get the user-friendly "name" of the "enum" value.

// Perform logic based on which "enum" value was chosen.
switch (authenticationMethodVariable.Value)
{
    case authenticationMethodVariable.Values.Forms: // Do something
        break;
    case authenticationMethodVariable.Values.Windows: // Do something
        break;
    case authenticationMethodVariable.Values.SSN: // Do something
        break;      
}

एक छोटा समाधान यह होगा कि आप एनमोंस {} को हटा दें और इसके बजाय आपने कितने एनमों का निर्माण किया है, इसकी एक स्थिर गणना रखें। इससे यह लाभ भी मिलता है कि आपको एनम सूची में किए गए नए उदाहरण को जोड़ना नहीं पड़ता है। उदाहरण के लिए public static int nextAvailable { get; private set; }फिर कंस्ट्रक्टर मेंthis.Value = nextAvailable++;
kjhf

दिलचस्प विचार @kjhf। मेरी चिंता हालांकि यह होगी कि यदि कोई कोड को पुन: क्रमित करता है, तो एनम मूल्यों को सौंपा गया मान भी बदल सकता है। उदाहरण के लिए, यह गलत इनम मान प्राप्त कर सकता है जब फ़ाइल / डेटाबेस में एनम मान को सहेजा जाता है, तो "नई प्रमाणीकरणमिथोड (...)" लाइनों के क्रम को बदल दिया जाता है (जैसे एक हटा दिया जाता है), और फिर एप्लिकेशन को फिर से चलाना और फ़ाइल / डेटाबेस से एनम मान प्राप्त करना; enum मान मूल रूप से सहेजे गए AuthenticationMethod से मेल नहीं खा सकता है।
deadlydog

अच्छा बिंदु - हालांकि मुझे उम्मीद है कि इन विशेष मामलों में लोग एनम के पूर्णांक मान (या एनोड कोड) पर भरोसा नहीं करेंगे। - और यह मान शुद्ध रूप से एक स्विच के रूप में उपयोग किया जाता है और संभवतः .Equals () और। GetHashCode ()। यदि संबंधित है, तो आप हमेशा "Do NOT REORDER" के साथ एक बड़ी टिप्पणी डाल सकते हैं: p
kjhf

क्या आप बस =ऑपरेटर को काम पर स्विच करने की अनुमति देने के लिए अधिभार नहीं डाल सकते ? मैंने वीबी में ऐसा किया था और अब select caseबयान में इसका इस्तेमाल कर सकता हूं ।
user1318499

@ user1318499 नहीं, C # में VB की तुलना में स्विच स्टेटमेंट के आसपास सख्त नियम हैं। आप केस स्टेटमेंट के लिए क्लास इंस्टेंसेस का उपयोग नहीं कर सकते हैं; आप केवल निरंतर आदिम का उपयोग कर सकते हैं।
deadlydog

13

मैं ऊपर दिए गए कई सुझावों के संयोजन का उपयोग करता हूं, कुछ कैशिंग के साथ। अब, मुझे कुछ कोड से विचार मिला जो मुझे नेट पर कहीं मिला था, लेकिन मुझे यह याद नहीं है कि मुझे यह कहां मिला या मुझे नहीं मिला। इसलिए यदि किसी को कभी भी कुछ ऐसा लगता है जो समान दिखता है तो कृपया टिप्पणी के साथ टिप्पणी करें।

वैसे भी, उपयोग में प्रकार कन्वर्टर्स शामिल हैं, इसलिए यदि आप यूआई के लिए बाध्य हैं तो यह 'बस काम करता है'। आप स्टैटिक मेथड्स में टाइप कन्वर्टर से इनिशियलाइज़ करके क्विक कोड लुकिंग के लिए जकुब के पैटर्न के साथ बढ़ा सकते हैं।

आधार का उपयोग इस तरह दिखेगा

[TypeConverter(typeof(CustomEnumTypeConverter<MyEnum>))]
public enum MyEnum
{
    // The custom type converter will use the description attribute
    [Description("A custom description")]
    ValueWithCustomDescription,

   // This will be exposed exactly.
   Exact
}

कस्टम एनम प्रकार कनवर्टर के लिए कोड निम्नानुसार है:

public class CustomEnumTypeConverter<T> : EnumConverter
    where T : struct
{
    private static readonly Dictionary<T,string> s_toString = 
      new Dictionary<T, string>();

    private static readonly Dictionary<string, T> s_toValue = 
      new Dictionary<string, T>();

    private static bool s_isInitialized;

    static CustomEnumTypeConverter()
    {
        System.Diagnostics.Debug.Assert(typeof(T).IsEnum,
          "The custom enum class must be used with an enum type.");
    }

    public CustomEnumTypeConverter() : base(typeof(T))
    {
        if (!s_isInitialized)
        {
            Initialize();
            s_isInitialized = true;
        }
    }

    protected void Initialize()
    {
        foreach (T item in Enum.GetValues(typeof(T)))
        {
            string description = GetDescription(item);
            s_toString[item] = description;
            s_toValue[description] = item;
        }
    }

    private static string GetDescription(T optionValue)
    {
        var optionDescription = optionValue.ToString();
        var optionInfo = typeof(T).GetField(optionDescription);
        if (Attribute.IsDefined(optionInfo, typeof(DescriptionAttribute)))
        {
            var attribute = 
              (DescriptionAttribute)Attribute.
                 GetCustomAttribute(optionInfo, typeof(DescriptionAttribute));
            return attribute.Description;
        }
        return optionDescription;
    }

    public override object ConvertTo(ITypeDescriptorContext context, 
       System.Globalization.CultureInfo culture, 
       object value, Type destinationType)
    {
        var optionValue = (T)value;

        if (destinationType == typeof(string) && 
            s_toString.ContainsKey(optionValue))
        {
            return s_toString[optionValue];
        }

        return base.ConvertTo(context, culture, value, destinationType);
    }

    public override object ConvertFrom(ITypeDescriptorContext context, 
       System.Globalization.CultureInfo culture, object value)
    {
        var stringValue = value as string;

        if (!string.IsNullOrEmpty(stringValue) && s_toValue.ContainsKey(stringValue))
        {
            return s_toValue[stringValue];
        }

        return base.ConvertFrom(context, culture, value);
    }
}

}


12

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

यदि आपको टाइप स्ट्रिंग की एक एनम की जरूरत नहीं है और (जो एक अभिन्न प्रकार नहीं है तो एनम का एक आधार नहीं हो सकता) यहां एक तरीका है:

    static class AuthenticationMethod
    {
        public static readonly string
            FORMS = "Forms",
            WINDOWSAUTHENTICATION = "WindowsAuthentication";
    }

आप इसे संदर्भित करने के लिए enum के समान सिंटैक्स का उपयोग कर सकते हैं

if (bla == AuthenticationMethod.FORMS)

यह संख्यात्मक मानों (संख्याओं के बजाय तारों की तुलना) के साथ थोड़ा धीमा होगा, लेकिन प्लस तरफ यह स्ट्रिंग तक पहुंचने के लिए प्रतिबिंब (धीमी) का उपयोग नहीं कर रहा है।


यदि आप "स्थैतिक" के बजाय "स्थैतिक" का उपयोग करते हैं तो आप स्विच स्टेटमेंट में मान लेबल के रूप में मानों का उपयोग कर सकते हैं।
एड एन।

11

मैंने इसे एक्सटेंशन विधि के रूप में कैसे हल किया:

using System.ComponentModel;
public static string GetDescription(this Enum value)
{
    var descriptionAttribute = (DescriptionAttribute)value.GetType()
        .GetField(value.ToString())
        .GetCustomAttributes(false)
        .Where(a => a is DescriptionAttribute)
        .FirstOrDefault();

    return descriptionAttribute != null ? descriptionAttribute.Description : value.ToString();
}

enum:

public enum OrderType
{
    None = 0,
    [Description("New Card")]
    NewCard = 1,
    [Description("Reload")]
    Refill = 2
}

उपयोग (जहां o.rderType, enum के समान नाम वाली संपत्ति है):

o.OrderType.GetDescription()

जो मुझे वास्तविक एनम वैल्यू न्यूकार्ड और रिफिल के बजाय "न्यू कार्ड" या "रीलोड" की एक स्ट्रिंग प्रदान करता है।


पूर्णता के लिए आपको अपनी विवरण श्रेणी की एक प्रति शामिल करनी चाहिए।
बर्नी व्हाइट


11

अपडेट: इस पेज पर जाने के बाद, 8 साल बाद, सी # को लंबे समय तक नहीं छूने के बाद, ऐसा लगता है कि मेरा जवाब अब सबसे अच्छा समाधान नहीं है। मैं वास्तव में विशेषता-कार्यों के साथ बंधे कनवर्टर समाधान को पसंद करता हूं।

यदि आप इसे पढ़ रहे हैं, तो कृपया सुनिश्चित करें कि आप अन्य उत्तरों को भी देखें।
(संकेत: वे इस एक से ऊपर हैं)


आप में से अधिकांश के रूप में, मुझे वास्तव में जैकब Šturc द्वारा चयनित उत्तर पसंद आया , लेकिन मुझे वास्तव में कॉपी-पेस्ट कोड से भी नफरत है, और जितना हो सके उतना कम करने की कोशिश करें।

इसलिए मैंने फैसला किया कि मैं एक EnumBase क्लास चाहता था जिसमें से अधिकांश कार्यक्षमता विरासत में मिली / अंतर्निहित है, जो मुझे व्यवहार के बजाय सामग्री पर ध्यान केंद्रित करने के लिए छोड़ देती है।

इस दृष्टिकोण के साथ मुख्य समस्या इस तथ्य पर आधारित है कि हालांकि एनम मान प्रकार-सुरक्षित उदाहरण हैं, इंटरैक्शन एनम वर्ग प्रकार के स्थैतिक कार्यान्वयन के साथ है। इसलिए जेनेरिक जादू की थोड़ी मदद से, मुझे लगता है कि मुझे आखिरकार सही मिश्रण मिला। आशा है कि किसी ने इसे उतना उपयोगी पाया जितना मैंने किया।

मैं जैकब के उदाहरण के साथ शुरुआत करूंगा, लेकिन विरासत और जेनरिक का उपयोग कर:

public sealed class AuthenticationMethod : EnumBase<AuthenticationMethod, int>
{
    public static readonly AuthenticationMethod FORMS =
        new AuthenticationMethod(1, "FORMS");
    public static readonly AuthenticationMethod WINDOWSAUTHENTICATION =
        new AuthenticationMethod(2, "WINDOWS");
    public static readonly AuthenticationMethod SINGLESIGNON =
        new AuthenticationMethod(3, "SSN");

    private AuthenticationMethod(int Value, String Name)
        : base( Value, Name ) { }
    public new static IEnumerable<AuthenticationMethod> All
    { get { return EnumBase<AuthenticationMethod, int>.All; } }
    public static explicit operator AuthenticationMethod(string str)
    { return Parse(str); }
}

और यहाँ आधार वर्ग है:

using System;
using System.Collections.Generic;
using System.Linq; // for the .AsEnumerable() method call

// E is the derived type-safe-enum class
// - this allows all static members to be truly unique to the specific
//   derived class
public class EnumBase<E, T> where E: EnumBase<E, T>
{
    #region Instance code
    public T Value { get; private set; }
    public string Name { get; private set; }

    protected EnumBase(T EnumValue, string Name)
    {
        Value = EnumValue;
        this.Name = Name;
        mapping.Add(Name, this);
    }

    public override string ToString() { return Name; }
    #endregion

    #region Static tools
    static private readonly Dictionary<string, EnumBase<E, T>> mapping;
    static EnumBase() { mapping = new Dictionary<string, EnumBase<E, T>>(); }
    protected static E Parse(string name)
    {
        EnumBase<E, T> result;
        if (mapping.TryGetValue(name, out result))
        {
            return (E)result;
        }

        throw new InvalidCastException();
    }
    // This is protected to force the child class to expose it's own static
    // method.
    // By recreating this static method at the derived class, static
    // initialization will be explicit, promising the mapping dictionary
    // will never be empty when this method is called.
    protected static IEnumerable<E> All
    { get { return mapping.Values.AsEnumerable().Cast<E>(); } }
    #endregion
}

आप आधार स्टेटिक कंस्ट्रक्टर से व्युत्पन्न स्टेटिक कंस्ट्रक्टर को कॉल करने में सक्षम हो सकते हैं। मैं अभी भी इसे देख रहा हूं, लेकिन अभी तक मुझे इसके साथ कोई समस्या नहीं मिली है: stackoverflow.com/questions/55290034/…
Cory-G

10

मैं कीथ के साथ सहमत हूं, लेकिन मैं वोट नहीं कर सकता (अभी तक)।

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

public static string ToSimpleString(this enum)
{
     switch (enum)
     {
         case ComplexForms:
             return "ComplexForms";
             break;
     }
}

public static string ToFormattedString(this enum)
{
     switch (enum)
     {
         case ComplexForms:
             return "Complex Forms";
             break;
     }
}

हालांकि, कुछ खातों से, यह एक संभावित रखरखाव दुःस्वप्न और कुछ कोड गंध की ओर जाता है। मैं लंबे समय तक और बहुत सारे ऐसे एनमों, या जो अक्सर बदलते रहते हैं, के लिए नज़र रखने की कोशिश करते हैं। अन्यथा, यह मेरे लिए एक महान समाधान रहा है।


10

यदि आप यहां एक सरल "एनम" को लागू करने के लिए देख रहे हैं, लेकिन जिसका मूल्य चींटियों के बजाय तार हैं, तो यहां सबसे सरल समाधान है:

    public sealed class MetricValueList
    {
        public static readonly string Brand = "A4082457-D467-E111-98DC-0026B9010912";
        public static readonly string Name = "B5B5E167-D467-E111-98DC-0026B9010912";
    }

कार्यान्वयन:

var someStringVariable = MetricValueList.Brand;

2
उपयोग करने के बजाय वेरिएबल्स कांस्टेबल बनाना बेहतर है static readonly
एंडीगीक

1
consts सार्वजनिक रूप से सुलभ वर्गों के लिए अच्छे नहीं हैं, क्योंकि वे संकलन समय में बेक किए जाते हैं, आप अपने पूरे कोड को कॉन्स्टिप के साथ फिर से जमा किए बिना किसी तीसरे पक्ष DLL को प्रतिस्थापित नहीं कर सकते हैं। स्थैतिक बनाम स्थिर पठनीयता का प्रदर्शन ऑफसेट नगण्य है।
क्रिस्टियन विलियम्स

7

जब मैं इस समस्या का सामना कर रहा हूं, तो कुछ सवाल हैं जिनका जवाब मैं पहले खोजने की कोशिश करता हूं:

  • क्या मेरे enum मानों के नाम उद्देश्य के लिए पर्याप्त रूप से अनुकूल हैं, या क्या मुझे मित्रता प्रदान करने की आवश्यकता है?
  • क्या मुझे चक्कर लगाने की ज़रूरत है? यही है, क्या मुझे पाठ मूल्यों को लेने और उन्हें एनम मूल्यों में पार्स करने की आवश्यकता होगी?
  • क्या यह ऐसा कुछ है जो मुझे अपने प्रोजेक्ट में कई एनमों के लिए करने की ज़रूरत है, या सिर्फ एक?
  • इस जानकारी को मैं किस तरह के यूआई तत्वों में प्रस्तुत करूंगा - विशेष रूप से, क्या मैं यूआई के लिए बाध्य होऊंगा, या संपत्ति शीट का उपयोग करूंगा?
  • क्या इसके लिए स्थानीय होने की आवश्यकता है?

ऐसा करने का सबसे सरल तरीका Enum.GetValue(और राउंड-ट्रिपिंग का उपयोग करके समर्थन Enum.Parse) है। यह भी अक्सर एक निर्माण के लायक है TypeConverter, जैसा कि स्टीव मितचम ने सुझाव दिया है, यूआई बंधन का समर्थन करने के लिए। ( TypeConverterजब आप प्रॉपर्टी शीट का उपयोग कर रहे हों, तब निर्माण करना आवश्यक नहीं है , जो प्रॉपर्टी शीट्स के बारे में अच्छी बातों में से एक है। हालांकि स्वामी जानते हैं कि उनके पास अपने मुद्दे हैं।)

सामान्य तौर पर, यदि उपरोक्त प्रश्नों के उत्तर से पता चलता है कि काम नहीं हो रहा है, तो मेरा अगला कदम एक स्थिर Dictionary<MyEnum, string>, या संभवतः एक को बनाना और आबाद करना है Dictionary<Type, Dictionary<int, string>>। मैं इंटरमीडिएट डेकोर-इन-कोड-एट्रिब्यूट्स स्टेप को छोड़ देता हूं क्योंकि आमतौर पर आगे आने वाले पाइक में तैनाती के बाद दोस्ताना मूल्यों को बदलने की आवश्यकता होती है (अक्सर, लेकिन हमेशा स्थानीयकरण के कारण नहीं)।


7

मैं इसे नीचे पोस्ट की गई टिप्पणी के रूप में पोस्ट करना चाहता था, लेकिन ऐसा नहीं कर सका क्योंकि मेरे पास पर्याप्त प्रतिनिधि नहीं है - इसलिए कृपया नीचे वोट न करें। कोड में एक त्रुटि थी और मैं इसे इस समाधान का उपयोग करने की कोशिश कर रहे व्यक्तियों को इंगित करना चाहता था:

[TypeConverter(typeof(CustomEnumTypeConverter(typeof(MyEnum))]
public enum MyEnum
{
  // The custom type converter will use the description attribute
  [Description("A custom description")]
  ValueWithCustomDescription,
  // This will be exposed exactly.
  Exact
}

होना चाहिए

[TypeConverter(typeof(CustomEnumTypeConverter<MyEnum>))]
public enum MyEnum
{
  // The custom type converter will use the description attribute
  [Description("A custom description")]
  ValueWithCustomDescription,

  // This will be exposed exactly.
  Exact
}

प्रतिभाशाली!


5

मेरा रूप

public struct Colors
{
    private String current;

    private static string red = "#ff0000";
    private static string green = "#00ff00";
    private static string blue = "#0000ff";

    private static IList<String> possibleColors; 

    public static Colors Red { get { return (Colors) red; } }
    public static Colors Green { get { return (Colors) green; } }
    public static Colors Blue { get { return (Colors) blue; } }

    static Colors()
    {
        possibleColors = new List<string>() {red, green, blue};
    }

    public static explicit operator String(Colors value)
    {
        return value.current;
    }

    public static explicit operator Colors(String value)
    {
        if (!possibleColors.Contains(value))
        {
            throw new InvalidCastException();
        }

        Colors color = new Colors();
        color.current = value;
        return color;
    }

    public static bool operator ==(Colors left, Colors right)
    {
        return left.current == right.current;
    }

    public static bool operator !=(Colors left, Colors right)
    {
        return left.current != right.current;
    }

    public bool Equals(Colors other)
    {
        return Equals(other.current, current);
    }

    public override bool Equals(object obj)
    {
        if (ReferenceEquals(null, obj)) return false;
        if (obj.GetType() != typeof(Colors)) return false;
        return Equals((Colors)obj);
    }

    public override int GetHashCode()
    {
        return (current != null ? current.GetHashCode() : 0);
    }

    public override string ToString()
    {
        return current;
    }
}

कोड थोड़ा बदसूरत लग रहा है, लेकिन इस संरचना के usages बहुत सुंदर हैं।

Colors color1 = Colors.Red;
Console.WriteLine(color1); // #ff0000

Colors color2 = (Colors) "#00ff00";
Console.WriteLine(color2); // #00ff00

// Colors color3 = "#0000ff"; // Compilation error
// String color4 = Colors.Red; // Compilation error

Colors color5 = (Colors)"#ff0000";
Console.WriteLine(color1 == color5); // True

Colors color6 = (Colors)"#00ff00";
Console.WriteLine(color1 == color6); // False

इसके अलावा, मुझे लगता है, यदि इस तरह के बहुत सारे आवश्यक हैं, तो कोड पीढ़ी (जैसे टी 4) का उपयोग किया जा सकता है।


4

विकल्प 1:

public sealed class FormsAuth
{
     public override string ToString{return "Forms Authtentication";}
}
public sealed class WindowsAuth
{
     public override string ToString{return "Windows Authtentication";}
}

public sealed class SsoAuth
{
     public override string ToString{return "SSO";}
}

और फिर

object auth = new SsoAuth(); //or whatever

//...
//...
// blablabla

DoSomethingWithTheAuth(auth.ToString());

विकल्प 2:

public enum AuthenticationMethod
{
        FORMS = 1,
        WINDOWSAUTHENTICATION = 2,
        SINGLESIGNON = 3
}

public class MyClass
{
    private Dictionary<AuthenticationMethod, String> map = new Dictionary<AuthenticationMethod, String>();
    public MyClass()
    {
         map.Add(AuthenticationMethod.FORMS,"Forms Authentication");
         map.Add(AuthenticationMethod.WINDOWSAUTHENTICATION ,"Windows Authentication");
         map.Add(AuthenticationMethod.SINGLESIGNON ,"SSo Authentication");
    }
}

4

यदि आप उस समस्या के बारे में सोचते हैं जिसे हम हल करने की कोशिश कर रहे हैं, तो यह एक ऐसी कल्पना नहीं है जिसकी हमें आवश्यकता है। हमें एक ऐसी वस्तु की आवश्यकता होती है, जो निश्चित संख्या में मूल्यों को प्रत्येक अभिभावक के साथ जोड़े रखने की अनुमति देती है; दूसरे शब्दों में, एक वर्ग को परिभाषित करने के लिए।

Jakub ubturc का टाइप-सेफ एनुम पैटर्न मेरे द्वारा यहां देखा गया सबसे अच्छा विकल्प है।

इसे देखो:

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

4

मेरे लिए, व्यावहारिक दृष्टिकोण वर्ग के अंदर वर्ग है, नमूना:

public class MSEModel
{
    class WITS
    {
        public const string DATE = "5005";
        public const string TIME = "5006";
        public const string MD = "5008";
        public const string ROP = "5075";
        public const string WOB = "5073";
        public const string RPM = "7001";
... 
    }

4

मैंने .NET में स्ट्रिंग-वैल्यू एनम बनाने के लिए बेस क्लास बनाया। यह सिर्फ एक सी # फाइल है जिसे आप अपनी परियोजनाओं में कॉपी और पेस्ट कर सकते हैं, या स्ट्रिंगगैनम नामक नुगेट पैकेज के माध्यम से स्थापित कर सकते हैं । गिटहब रेपो

  • अगर xml टिप्पणी के साथ वर्ग एनोटेट किया जाता है, तो Intellisense enum नाम का सुझाव देगा <completitionlist>। (C # और VB दोनों में काम करता है)

Intellisense का डेमो

  • एक नियमित एनम के समान उपयोग:
///<completionlist cref="HexColor"/> 
class HexColor : StringEnum<HexColor>
{
    public static readonly HexColor Blue = Create("#FF0000");
    public static readonly HexColor Green = Create("#00FF00");
    public static readonly HexColor Red = Create("#000FF");
}
    // Static Parse Method
    HexColor.Parse("#FF0000") // => HexColor.Red
    HexColor.Parse("#ff0000", caseSensitive: false) // => HexColor.Red
    HexColor.Parse("invalid") // => throws InvalidOperationException

    // Static TryParse method.
    HexColor.TryParse("#FF0000") // => HexColor.Red
    HexColor.TryParse("#ff0000", caseSensitive: false) // => HexColor.Red
    HexColor.TryParse("invalid") // => null

    // Parse and TryParse returns the preexistent instances
    object.ReferenceEquals(HexColor.Parse("#FF0000"), HexColor.Red) // => true

    // Conversion from your `StringEnum` to `string`
    string myString1 = HexColor.Red.ToString(); // => "#FF0000"
    string myString2 = HexColor.Red; // => "#FF0000" (implicit cast)

instalation:

  • अपनी परियोजना के लिए निम्नलिखित स्ट्रिंग बेस क्लास को पेस्ट करें। ( नवीनतम संस्करण )
  • या StringEnum NuGet पैकेज स्थापित करें , जो कि इस पर आधारित है .Net Standard 1.0ताकि यह .Net Core= = 1.0, .Net Framework> = 4.5, Mono> 4.6 /> आदि पर चले
    /// <summary>
    /// Base class for creating string-valued enums in .NET.<br/>
    /// Provides static Parse() and TryParse() methods and implicit cast to string.
    /// </summary>
    /// <example> 
    /// <code>
    /// class Color : StringEnum &lt;Color&gt;
    /// {
    ///     public static readonly Color Blue = Create("Blue");
    ///     public static readonly Color Red = Create("Red");
    ///     public static readonly Color Green = Create("Green");
    /// }
    /// </code>
    /// </example>
    /// <typeparam name="T">The string-valued enum type. (i.e. class Color : StringEnum&lt;Color&gt;)</typeparam>
    public abstract class StringEnum<T> : IEquatable<T> where T : StringEnum<T>, new()
    {
        protected string Value;
        private static Dictionary<string, T> valueDict = new Dictionary<string, T>();
        protected static T Create(string value)
        {
            if (value == null)
                return null; // the null-valued instance is null.

            var result = new T() { Value = value };
            valueDict.Add(value, result);
            return result;
        }

        public static implicit operator string(StringEnum<T> enumValue) => enumValue.Value;
        public override string ToString() => Value;

        public static bool operator !=(StringEnum<T> o1, StringEnum<T> o2) => o1?.Value != o2?.Value;
        public static bool operator ==(StringEnum<T> o1, StringEnum<T> o2) => o1?.Value == o2?.Value;

        public override bool Equals(object other) => this.Value.Equals((other as T)?.Value ?? (other as string));
        bool IEquatable<T>.Equals(T other) => this.Value.Equals(other.Value);
        public override int GetHashCode() => Value.GetHashCode();

        /// <summary>
        /// Parse the <paramref name="value"/> specified and returns a valid <typeparamref name="T"/> or else throws InvalidOperationException.
        /// </summary>
        /// <param name="value">The string value representad by an instance of <typeparamref name="T"/>. Matches by string value, not by the member name.</param>
        /// <param name="caseSensitive">If true, the strings must match case and takes O(log n). False allows different case but is little bit slower (O(n))</param>
        public static T Parse(string value, bool caseSensitive = true)
        {
            var result = TryParse(value, caseSensitive);
            if (result == null)
                throw new InvalidOperationException((value == null ? "null" : $"'{value}'") + $" is not a valid {typeof(T).Name}");

            return result;
        }

        /// <summary>
        /// Parse the <paramref name="value"/> specified and returns a valid <typeparamref name="T"/> or else returns null.
        /// </summary>
        /// <param name="value">The string value representad by an instance of <typeparamref name="T"/>. Matches by string value, not by the member name.</param>
        /// <param name="caseSensitive">If true, the strings must match case. False allows different case but is slower: O(n)</param>
        public static T TryParse(string value, bool caseSensitive = true)
        {
            if (value == null) return null;
            if (valueDict.Count == 0) System.Runtime.CompilerServices.RuntimeHelpers.RunClassConstructor(typeof(T).TypeHandle); // force static fields initialization
            if (caseSensitive)
            {
                if (valueDict.TryGetValue(value, out T item))
                    return item;
                else
                    return null;
            }
            else
            {
                // slower O(n) case insensitive search
                return valueDict.FirstOrDefault(f => f.Key.Equals(value, StringComparison.OrdinalIgnoreCase)).Value;
                // Why Ordinal? => https://esmithy.net/2007/10/15/why-stringcomparisonordinal-is-usually-the-right-choice/
            }
        }
    }

3

यहाँ एक और तरीका है, जो एनमों के साथ तार जोड़ने के काम को पूरा करता है:

struct DATABASE {
    public enum enums {NOTCONNECTED, CONNECTED, ERROR}
    static List<string> strings =
        new List<string>() {"Not Connected", "Connected", "Error"};

    public string GetString(DATABASE.enums value) {
        return strings[(int)value];
    }
}

इस विधि को इस तरह कहा जाता है:

public FormMain() {
    DATABASE dbEnum;

    string enumName = dbEnum.GetString(DATABASE.enums.NOTCONNECTED);
}

आप अपनी स्वयं की संरचना में संबंधित एनमों को समूहीकृत कर सकते हैं। चूँकि यह विधि Enum प्रकार का उपयोग करती है, आप Intellisense का उपयोग कर बनाते समय enums की सूची प्रदर्शित करने के लिए कर सकते हैंGetString() कॉल ।

आप वैकल्पिक रूप से DATABASEसंरचना पर नए ऑपरेटर का उपयोग कर सकते हैं । इसका उपयोग नहीं करने का मतलब है कि तार Listको तब तक आवंटित नहीं किया जाता है जब तक कि पहली GetString()कॉल नहीं की जाती है।


3

यहाँ बहुत सारे शानदार जवाब हैं, लेकिन मेरे मामले में यह हल नहीं हुआ कि मैं "स्ट्रिंग एनम" से क्या चाहता था, जो था:

  1. स्विच स्टेटमेंट में प्रयोग करने योग्य उदाहरण स्विच (myEnum)
  2. समारोह मापदंडों में इस्तेमाल किया जा सकता है जैसे फू (myEnum प्रकार)
  3. संदर्भित किया जा सकता है जैसे myEnum.FirstElement
  4. मैं स्ट्रिंग्स का उपयोग कर सकता हूं जैसे foo ("FirstElement") == foo (myEnum.FirstElement)

1,2 और 4 वास्तव में एक स्ट्रिंग के C # टाइप के साथ हल किया जा सकता है (क्योंकि तार c # में switchable हैं)

3 स्थैतिक का तार द्वारा हल किया जा सकता है। इसलिए यदि आपकी ज़रूरतें समान हैं, तो यह सबसे आसान तरीका है:

public sealed class Types
{

    private readonly String name;

    private Types(String name)
    {
        this.name = name;

    }

    public override String ToString()
    {
        return name;
    }

    public static implicit operator Types(string str)
    {
        return new Types(str);

    }
    public static implicit operator string(Types str)
    {
        return str.ToString();
    }


    #region enum

    public const string DataType = "Data";
    public const string ImageType = "Image";
    public const string Folder = "Folder";
    #endregion

}

यह उदाहरण के लिए अनुमति देता है:

    public TypeArgs(Types SelectedType)
    {
        Types SelectedType = SelectedType
    }

तथा

public TypeObject CreateType(Types type)
    {
        switch (type)
        {

            case Types.ImageType:
              //
                break;

            case Types.DataType:
             //
                break;

        }
    }

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

अब एक पूर्णांक मूल्य आप (शायद तुलना गति के लिए) के लिए महत्वपूर्ण था, तो आप सकता है जेकब Šturc शानदार जवाब से कुछ विचारों का उपयोग करें और कुछ एक कर थोड़ा पागल, इस इस पर मेरी वार है:

    public sealed class Types
{
    private static readonly Dictionary<string, Types> strInstance = new Dictionary<string, Types>();
    private static readonly Dictionary<int, Types> intInstance = new Dictionary<int, Types>();

    private readonly String name;
    private static int layerTypeCount = 0;
    private int value;
    private Types(String name)
    {
        this.name = name;
        value = layerTypeCount++;
        strInstance[name] = this;
        intInstance[value] = this;
    }

    public override String ToString()
    {
        return name;
    }


    public static implicit operator Types(int val)
    {
        Types result;
        if (intInstance.TryGetValue(val, out result))
            return result;
        else
            throw new InvalidCastException();
    }

    public static implicit operator Types(string str)
    {
        Types result;
        if (strInstance.TryGetValue(str, out result))
        {
            return result;
        }
        else
        {
            result = new Types(str);
            return result;
        }

    }
    public static implicit operator string(Types str)
    {
        return str.ToString();
    }

    public static bool operator ==(Types a, Types b)
    {
        return a.value == b.value;
    }
    public static bool operator !=(Types a, Types b)
    {
        return a.value != b.value;
    }

    #region enum

    public const string DataType = "Data";
    public const string ImageType = "Image";

    #endregion

}

लेकिन निश्चित रूप से "प्रकार बॉब = 4;" तब तक निरर्थक होगा जब तक कि आपने उन्हें पहले शुरू नहीं किया था जो कि बिंदु को हराने का था ...

लेकिन सिद्धांत में TypeA == TypeB जल्दी होगा ...


3

यदि मैं आपको सही ढंग से समझ रहा हूं, तो आप बस .ToString () को मान से एनम के नाम को पुनः प्राप्त करने के लिए उपयोग कर सकते हैं (मान लें कि यह पहले से ही एनम के रूप में डाली गई है); यदि आपके पास नग्न इरादा था (एक डेटाबेस या कुछ से कहने देता है) तो आप पहले इसे एनम को दे सकते हैं। नीचे दिए गए दोनों तरीकों से आपको एनम नाम मिलेगा।

AuthenticationMethod myCurrentSetting = AuthenticationMethod.FORMS;
Console.WriteLine(myCurrentSetting); // Prints: FORMS
string name = Enum.GetNames(typeof(AuthenticationMethod))[(int)myCurrentSetting-1];
Console.WriteLine(name); // Prints: FORMS

हालांकि, ध्यान रखें कि दूसरी तकनीक यह मानती है कि आप ints का उपयोग कर रहे हैं और आपका सूचकांक 1 आधारित है (0 आधारित नहीं)। फ़ंक्शन GetNames भी तुलना से काफी भारी है, आप प्रत्येक बार जब यह कहते हैं, तो एक संपूर्ण सरणी उत्पन्न कर रहे हैं। जैसा कि आप पहली तकनीक में देख सकते हैं, .ToString () वास्तव में अंतर्निहित रूप से कहा जाता है। इन दोनों को पहले से ही निश्चित रूप से जवाब में वर्णित किया गया है, मैं सिर्फ उन दोनों के बीच अंतर को स्पष्ट करने की कोशिश कर रहा हूं।


3

पुरानी पोस्ट लेकिन ...

इसका उत्तर वास्तव में बहुत सरल हो सकता है। Enum.ToString () फ़ंक्शन का उपयोग करें

इस फ़ंक्शन के 6 अधिभार हैं, आप स्ट्रिंग मान वापस करने के लिए Enum.Tostring ("F") या Enum.ToString () का उपयोग कर सकते हैं। किसी और चीज से परेशान होने की जरूरत नहीं है। यहाँ एक कार्यशील डेमो है

ध्यान दें कि यह समाधान सभी संकलक के लिए काम नहीं कर सकता है ( यह डेमो अपेक्षा के अनुरूप काम नहीं करता है ) लेकिन कम से कम यह नवीनतम संकलक के लिए काम करता है।


2

MSDN पर आधारित: http://msdn.microsoft.com/en-us/library/cc138362.aspx

foreach (string str in Enum.GetNames(typeof(enumHeaderField)))
{
    Debug.WriteLine(str);
}

str खेतों के नाम होंगे


2
यह एनम का नाम देगा, आप उसके लिए ToString () का उपयोग कर सकते हैं, यह वह नहीं है जो पूछा गया था। चेकआउट msdn.microsoft.com/en-us/library/system.enum.getname.aspx अपने bubu के बारे में अधिक जानकारी के लिए
मिकी पर्लेस्टीन

2

खैर, उपरोक्त सभी को पढ़ने के बाद मुझे लगता है कि लोगों ने एन्यूमरेटरों को तार में बदलने के मुद्दे को जटिल बना दिया है। मुझे एनुमेरेटेड फ़ील्ड्स पर विशेषताएँ होने का विचार पसंद आया, लेकिन मुझे लगता है कि मुख्य रूप से मेटा-डेटा के लिए विशेषताओं का उपयोग किया जाता है, लेकिन आपके मामले में मुझे लगता है कि आपको सभी प्रकार के स्थानीयकरण चाहिए।

public enum Color 
{ Red = 1, Green = 2, Blue = 3}


public static EnumUtils 
{
   public static string GetEnumResourceString(object enumValue)
    {
        Type enumType = enumValue.GetType();
        string value = Enum.GetName(enumValue.GetType(), enumValue);
        string resourceKey = String.Format("{0}_{1}", enumType.Name, value);
        string result = Resources.Enums.ResourceManager.GetString(resourceKey);
        if (string.IsNullOrEmpty(result))
        {
            result = String.Format("{0}", value);
        }
        return result;
    }
}

अब यदि हम उपरोक्त विधि को कॉल करने का प्रयास करते हैं तो हम इसे इस तरह से कॉल कर सकते हैं

public void Foo()
{
  var col = Color.Red;
  Console.WriteLine (EnumUtils.GetEnumResourceString (col));
}

आपको बस इतना करने की ज़रूरत है कि सभी एन्यूमरेटर मानों और संबंधित स्ट्रिंग्स वाले एक संसाधन फ़ाइल बनाएं

संसाधन का नाम संसाधन मान
Color_Red My String रंग लाल में
Color_Blue Blueeey
रंग_ग्रीन हल्क रंग

क्या वास्तव में इसके बारे में बहुत अच्छा है कि यह बहुत उपयोगी होगा यदि आपको अपने आवेदन को स्थानीयकृत करने की आवश्यकता है, क्योंकि आपको केवल अपनी नई भाषा के साथ एक और संसाधन फ़ाइल बनाने की आवश्यकता है! और वी-ला!


1

जब मैं इस तरह की स्थिति में होता हूं तो नीचे दिए गए समाधान का प्रस्ताव करता हूं।

और एक उपभोग करने वाले वर्ग के रूप में आप हो सकते हैं

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace MyApp.Dictionaries
{
    class Greek
    {

        public static readonly string Alpha = "Alpha";
        public static readonly string Beta = "Beta";
        public static readonly string Gamma = "Gamma";
        public static readonly string Delta = "Delta";


        private static readonly BiDictionary<int, string> Dictionary = new BiDictionary<int, string>();


        static Greek() {
            Dictionary.Add(1, Alpha);
            Dictionary.Add(2, Beta);
            Dictionary.Add(3, Gamma);
            Dictionary.Add(4, Delta);
        }

        public static string getById(int id){
            return Dictionary.GetByFirst(id);
        }

        public static int getByValue(string value)
        {
            return Dictionary.GetBySecond(value);
        }

    }
}

और एक द्विदिश शब्दकोश का उपयोग करना: इसके आधार पर ( https://stackoverflow.com/a/255638/986160 ) यह मानते हुए कि चाबियाँ शब्दकोश में एकल मूल्यों से जुड़ी होंगी और इसके समान ( https://stackoverflow.com/a) / 255630/986160 ) लेकिन थोड़ा और अधिक सुरुचिपूर्ण। यह डिक्शनरी भी दमदार है और आप इन्टस से स्ट्रिंग्स तक आगे-पीछे जा सकते हैं। इसके अलावा आपको इस वर्ग के अपवाद के साथ अपने कोडबेस में कोई स्ट्रिंग करने की आवश्यकता नहीं है।

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Collections;

namespace MyApp.Dictionaries
{

    class BiDictionary<TFirst, TSecond> : IEnumerable
    {
        IDictionary<TFirst, TSecond> firstToSecond = new Dictionary<TFirst, TSecond>();
        IDictionary<TSecond, TFirst> secondToFirst = new Dictionary<TSecond, TFirst>();

        public void Add(TFirst first, TSecond second)
        {
            firstToSecond.Add(first, second);
            secondToFirst.Add(second, first);
        }

        public TSecond this[TFirst first]
        {
            get { return GetByFirst(first); }
        }

        public TFirst this[TSecond second]
        {
            get { return GetBySecond(second); }
        }

        public TSecond GetByFirst(TFirst first)
        {
            return firstToSecond[first];
        }

        public TFirst GetBySecond(TSecond second)
        {
            return secondToFirst[second];
        }

        public IEnumerator GetEnumerator()
        {
            return GetFirstEnumerator();
        }

        public IEnumerator GetFirstEnumerator()
        {
            return firstToSecond.GetEnumerator();
        }

        public IEnumerator GetSecondEnumerator()
        {
            return secondToFirst.GetEnumerator();
        }
    }
}

1

बड़े स्ट्रिंग एनम सेट के लिए, सूचीबद्ध उदाहरण थकाऊ बन सकते हैं। यदि आप स्थिति कोड की सूची, या अन्य स्ट्रिंग आधारित एनम की सूची चाहते हैं, तो एक विशेषता प्रणाली का उपयोग करने के लिए कष्टप्रद है, और स्वयं के उदाहरणों के साथ एक स्थिर वर्ग कॉन्फ़िगर करने के लिए कष्टप्रद है। अपने स्वयं के समाधान के लिए, मैं टी 4 टेम्प्लेटिंग का उपयोग करता हूं ताकि स्ट्रिंग-समर्थित एनमों को आसानी से हो सके। नतीजा यह निकलता है कि HttpMethod वर्ग कैसे काम करता है।

आप इसे इस तरह से उपयोग कर सकते हैं:

    string statusCode = ResponseStatusCode.SUCCESS; // Automatically converts to string when needed
    ResponseStatusCode codeByValueOf = ResponseStatusCode.ValueOf(statusCode); // Returns null if not found

    // Implements TypeConverter so you can use it with string conversion methods.
    var converter = System.ComponentModel.TypeDescriptor.GetConverter(typeof(ResponseStatusCode));
    ResponseStatusCode code = (ResponseStatusCode) converter.ConvertFromInvariantString(statusCode);

    // You can get a full list of the values
    bool canIterateOverValues = ResponseStatusCode.Values.Any(); 

    // Comparisons are by value of the "Name" property. Not by memory pointer location.
    bool implementsByValueEqualsEqualsOperator = "SUCCESS" == ResponseStatusCode.SUCCESS; 

आप Enum.tt फ़ाइल से प्रारंभ करते हैं।

<#@ include file="StringEnum.ttinclude" #>


<#+
public static class Configuration
{
    public static readonly string Namespace = "YourName.Space";
    public static readonly string EnumName = "ResponseStatusCode";
    public static readonly bool IncludeComments = true;

    public static readonly object Nodes = new
    {
        SUCCESS = "The response was successful.",
        NON_SUCCESS = "The request was not successful.",
        RESOURCE_IS_DISCONTINUED = "The resource requested has been discontinued and can no longer be accessed."
    };
}
#>

उसके बाद, आप अपनी StringEnum.ttinclude फ़ाइल में जोड़ें।

<#@ template debug="false" hostspecific="false" language="C#" #>
<#@ assembly name="System.Core" #>
<#@ import namespace="System" #>
<#@ import namespace="System.Linq" #>
<#@ import namespace="System.Text" #>
<#@ import namespace="System.Reflection" #>
<#@ import namespace="System.Collections.Generic" #>
<#@ output extension=".cs" #>
<#@ CleanupBehavior processor="T4VSHost" CleanupAfterProcessingtemplate="true" #>

//------------------------------------------------------------------------------
// <auto-generated>
//     This code was generated by a tool.
//
//     Changes to this file may cause incorrect behavior and will be lost if
//     the code is regenerated.
// </auto-generated>
//------------------------------------------------------------------------------

using System;
using System.Linq;
using System.Collections.Generic;
using System.ComponentModel;
using System.Globalization;

namespace <#= Configuration.Namespace #>
{
    /// <summary>
    /// TypeConverter implementations allow you to use features like string.ToNullable(T).
    /// </summary>
    public class <#= Configuration.EnumName #>TypeConverter : TypeConverter
    {
        public override bool CanConvertFrom(ITypeDescriptorContext context, Type sourceType)
        {
            return sourceType == typeof(string) || base.CanConvertFrom(context, sourceType);
        }

        public override object ConvertFrom(ITypeDescriptorContext context, CultureInfo culture, object value)
        {
            var casted = value as string;

            if (casted != null)
            {
                var result = <#= Configuration.EnumName #>.ValueOf(casted);
                if (result != null)
                {
                    return result;
                }
            }

            return base.ConvertFrom(context, culture, value);
        }

        public override object ConvertTo(ITypeDescriptorContext context, CultureInfo culture, object value, Type destinationType)
        {
            var casted = value as <#= Configuration.EnumName #>;
            if (casted != null && destinationType == typeof(string))
            {
                return casted.ToString();
            }

            return base.ConvertTo(context, culture, value, destinationType);
        }
    }

    [TypeConverter(typeof(<#= Configuration.EnumName #>TypeConverter))]
    public class <#= Configuration.EnumName #> : IEquatable<<#= Configuration.EnumName #>>
    {
//---------------------------------------------------------------------------------------------------
// V A L U E S _ L I S T
//---------------------------------------------------------------------------------------------------
<# Write(Helpers.PrintEnumProperties(Configuration.Nodes)); #>

        private static List<<#= Configuration.EnumName #>> _list { get; set; } = null;
        public static List<<#= Configuration.EnumName #>> ToList()
        {
            if (_list == null)
            {
                _list = typeof(<#= Configuration.EnumName #>).GetFields().Where(x => x.IsStatic && x.IsPublic && x.FieldType == typeof(<#= Configuration.EnumName #>))
                    .Select(x => x.GetValue(null)).OfType<<#= Configuration.EnumName #>>().ToList();
            }

            return _list;
        }

        public static List<<#= Configuration.EnumName #>> Values()
        {
            return ToList();
        }

        /// <summary>
        /// Returns the enum value based on the matching Name of the enum. Case-insensitive search.
        /// </summary>
        /// <param name="key"></param>
        /// <returns></returns>
        public static <#= Configuration.EnumName #> ValueOf(string key)
        {
            return ToList().FirstOrDefault(x => string.Compare(x.Name, key, true) == 0);
        }


//---------------------------------------------------------------------------------------------------
// I N S T A N C E _ D E F I N I T I O N
//---------------------------------------------------------------------------------------------------      
        public string Name { get; private set; }
        public string Description { get; private set; }
        public override string ToString() { return this.Name; }

        /// <summary>
        /// Implcitly converts to string.
        /// </summary>
        /// <param name="d"></param>
        public static implicit operator string(<#= Configuration.EnumName #> d)
        {
            return d.ToString();
        }

        /// <summary>
        /// Compares based on the == method. Handles nulls gracefully.
        /// </summary>
        /// <param name="a"></param>
        /// <param name="b"></param>
        /// <returns></returns>
        public static bool operator !=(<#= Configuration.EnumName #> a, <#= Configuration.EnumName #> b)
        {
            return !(a == b);
        }

        /// <summary>
        /// Compares based on the .Equals method. Handles nulls gracefully.
        /// </summary>
        /// <param name="a"></param>
        /// <param name="b"></param>
        /// <returns></returns>
        public static bool operator ==(<#= Configuration.EnumName #> a, <#= Configuration.EnumName #> b)
        {
            return a?.ToString() == b?.ToString();
        }

        /// <summary>
        /// Compares based on the .ToString() method
        /// </summary>
        /// <param name="o"></param>
        /// <returns></returns>
        public override bool Equals(object o)
        {
            return this.ToString() == o?.ToString();
        }

        /// <summary>
        /// Compares based on the .ToString() method
        /// </summary>
        /// <param name="other"></param>
        /// <returns></returns>
        public bool Equals(<#= Configuration.EnumName #> other)
        {
            return this.ToString() == other?.ToString();
        }

        /// <summary>
        /// Compares based on the .Name property
        /// </summary>
        /// <returns></returns>
        public override int GetHashCode()
        {
            return this.Name.GetHashCode();
        }
    }
}

<#+

public static class Helpers
{
        public static string PrintEnumProperties(object nodes)
        {
            string o = "";
            Type nodesTp = Configuration.Nodes.GetType();
            PropertyInfo[] props = nodesTp.GetProperties().OrderBy(p => p.Name).ToArray();

            for(int i = 0; i < props.Length; i++)
            {
                var prop = props[i];
                if (Configuration.IncludeComments)
                {
                    o += "\r\n\r\n";
                    o += "\r\n        ///<summary>";
                    o += "\r\n        /// "+Helpers.PrintPropertyValue(prop, Configuration.Nodes);
                    o += "\r\n        ///</summary>";
                }

                o += "\r\n        public static readonly "+Configuration.EnumName+" "+prop.Name+ " = new "+Configuration.EnumName+"(){ Name = \""+prop.Name+"\", Description = "+Helpers.PrintPropertyValue(prop, Configuration.Nodes)+ "};";
            }

            o += "\r\n\r\n";

            return o;
        }

        private static Dictionary<string, string> GetValuesMap()
        {
            Type nodesTp = Configuration.Nodes.GetType();
            PropertyInfo[] props= nodesTp.GetProperties();
            var dic = new Dictionary<string,string>();
            for(int i = 0; i < props.Length; i++)
            {
                var prop = nodesTp.GetProperties()[i];
                dic[prop.Name] = prop.GetValue(Configuration.Nodes).ToString();
            }
            return dic;
        }

        public static string PrintMasterValuesMap(object nodes)
        {
            Type nodesTp = Configuration.Nodes.GetType();
            PropertyInfo[] props= nodesTp.GetProperties();
            string o = "        private static readonly Dictionary<string, string> ValuesMap = new Dictionary<string, string>()\r\n        {";
            for(int i = 0; i < props.Length; i++)
            {
                var prop = nodesTp.GetProperties()[i];
                o += "\r\n            { \""+prop.Name+"\", "+(Helpers.PrintPropertyValue(prop,Configuration.Nodes)+" },");
            }
            o += ("\r\n        };\r\n");

            return o;
        }


        public static string PrintPropertyValue(PropertyInfo prop, object objInstance)
        {
            switch(prop.PropertyType.ToString()){
                case "System.Double":
                    return prop.GetValue(objInstance).ToString()+"D";
                case "System.Float":
                    return prop.GetValue(objInstance).ToString()+"F";
                case "System.Decimal":
                    return prop.GetValue(objInstance).ToString()+"M";
                case "System.Long":
                    return prop.GetValue(objInstance).ToString()+"L";
                case "System.Boolean":
                case "System.Int16":
                case "System.Int32":
                    return prop.GetValue(objInstance).ToString().ToLowerInvariant();
                case "System.String":
                    return "\""+prop.GetValue(objInstance)+"\"";
            }

            return prop.GetValue(objInstance).ToString();
        }

        public static string _ (int numSpaces)
        {
            string o = "";
            for(int i = 0; i < numSpaces; i++){
                o += " ";
            }

            return o;
        }
}
#>

अंत में, आप अपनी Enum.tt फ़ाइल को पुन: व्यवस्थित करते हैं और आउटपुट इस तरह दिखता है:

//------------------------------------------------------------------------------
// <auto-generated>
//     This code was generated by a tool.
//
//     Changes to this file may cause incorrect behavior and will be lost if
//     the code is regenerated.
// </auto-generated>
//------------------------------------------------------------------------------

using System;
using System.Linq;
using System.Collections.Generic;

namespace YourName.Space
{
    public class ResponseStatusCode
    {
//---------------------------------------------------------------------------------------------------
// V A L U E S _ L I S T 
//---------------------------------------------------------------------------------------------------



        ///<summary>
        /// "The response was successful."
        ///</summary>
        public static readonly ResponseStatusCode SUCCESS = new ResponseStatusCode(){ Name = "SUCCESS", Description = "The response was successful."};


        ///<summary>
        /// "The request was not successful."
        ///</summary>
        public static readonly ResponseStatusCode NON_SUCCESS = new ResponseStatusCode(){ Name = "NON_SUCCESS", Description = "The request was not successful."};


        ///<summary>
        /// "The resource requested has been discontinued and can no longer be accessed."
        ///</summary>
        public static readonly ResponseStatusCode RESOURCE_IS_DISCONTINUED = new ResponseStatusCode(){ Name = "RESOURCE_IS_DISCONTINUED", Description = "The resource requested has been discontinued and can no longer be accessed."};


        private static List<ResponseStatusCode> _list { get; set; } = null;
        public static List<ResponseStatusCode> ToList()
        {
            if (_list == null)
            {
                _list = typeof(ResponseStatusCode).GetFields().Where(x => x.IsStatic && x.IsPublic && x.FieldType == typeof(ResponseStatusCode))
                    .Select(x => x.GetValue(null)).OfType<ResponseStatusCode>().ToList();
            }

            return _list;
        }

        public static List<ResponseStatusCode> Values()
        {
            return ToList();
        }

        /// <summary>
        /// Returns the enum value based on the matching Name of the enum. Case-insensitive search.
        /// </summary>
        /// <param name="key"></param>
        /// <returns></returns>
        public static ResponseStatusCode ValueOf(string key)
        {
            return ToList().FirstOrDefault(x => string.Compare(x.Name, key, true) == 0);
        }


//---------------------------------------------------------------------------------------------------
// I N S T A N C E _ D E F I N I T I O N 
//---------------------------------------------------------------------------------------------------       
        public string Name { get; set; }
        public string Description { get; set; }
        public override string ToString() { return this.Name; }

        /// <summary>
        /// Implcitly converts to string.
        /// </summary>
        /// <param name="d"></param>
        public static implicit operator string(ResponseStatusCode d)
        {
            return d.ToString();
        }

        /// <summary>
        /// Compares based on the == method. Handles nulls gracefully.
        /// </summary>
        /// <param name="a"></param>
        /// <param name="b"></param>
        /// <returns></returns>
        public static bool operator !=(ResponseStatusCode a, ResponseStatusCode b)
        {
            return !(a == b);
        }

        /// <summary>
        /// Compares based on the .Equals method. Handles nulls gracefully.
        /// </summary>
        /// <param name="a"></param>
        /// <param name="b"></param>
        /// <returns></returns>
        public static bool operator ==(ResponseStatusCode a, ResponseStatusCode b)
        {
            return a?.ToString() == b?.ToString();
        }

        /// <summary>
        /// Compares based on the .ToString() method
        /// </summary>
        /// <param name="o"></param>
        /// <returns></returns>
        public override bool Equals(object o)
        {
            return this.ToString() == o?.ToString();
        }

        /// <summary>
        /// Compares based on the .Name property
        /// </summary>
        /// <returns></returns>
        public override int GetHashCode()
        {
            return this.Name.GetHashCode();
        }
    }
}
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.