दिलचस्प पोस्ट
एनजीएन 504 गेटवे टाइमआउट को रोकें PHP set_time_limit () दो सूचियों / ट्यूपल्स में जोड़े की एक सूची / टपल को अनपैक करना एक PyQt अनुप्रयोग में IPython Qt कंसोल को एम्बेड करना JTextArea से एक कुंजी प्राप्त करें OnGlobalLayoutListener: बहिष्कार और अनुकूलता एक वैकल्पिक फैशन में दो सूचियों को गठबंधन करने का पायथनिक तरीका है? नियमित अभिव्यक्ति | लीप इयर्स और अधिक कोणीय 2 आंतरिक एचटीएमएल (क्लिक) बाइंडिंग क्या `: key =>" value "` और `key:" value "` हैश नोटेशन के बीच कोई अंतर है? मोंगोडीबी के साथ लोचदार खोज का उपयोग कैसे करें? PHP में क्लाइंट आईपी पता कैसे प्राप्त करें? Google मानचित्र API v3 – सेट सीमा और केंद्र आप सरल PostgreSQL स्क्रिप्ट में चर का उपयोग कैसे करते हैं? सी में एन्यूमरेटेड टाइप (एन्यूम) को कैसे परिभाषित किया जाए? एक DataTable में एन डेटाटैबल्स का संयोजन

सी # स्ट्रिंग एंमाम

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

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

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

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

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

 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 } 

और निश्चित रूप से मुझे स्ट्रिंगवॉल्यू प्राप्त करने के लिए कुछ चाहिए:

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

ठीक है अब ये सब काम एक जादू की तरह है लेकिन मुझे यह बहुत काम मिल रहा है मैं सोच रहा था कि इसके लिए एक बेहतर समाधान है।

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

वेब के समाधान से एकत्रित समाधान "सी # स्ट्रिंग एंमाम"

टाइप-सुरक्षित-एन्म पैटर्न की कोशिश करें

 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 क्रम में "enum सदस्य" फ़ील्ड का प्रारंभिकरण नल रेफरेंस अपवाद को फेंकता नहीं है, उदाहरण के लिए कंसट्रक्टर को कॉल करने से, अपनी कक्षा में "एंनाम सदस्य" फ़ील्ड के सामने डिक्शनरी फ़ील्ड डालना सुनिश्चित करें। इसका कारण यह है कि स्थैतिक फ़ील्ड प्रारंभकर्ताओं को घोषणा क्रम में तथा स्थिर निर्माता के समक्ष कहा जाता है, अजीब और आवश्यक लेकिन भ्रामक स्थिति पैदा करने से पहले सभी स्थैतिक फ़ील्ड्स के प्रारंभ होने के पहले इंस्टेंस कन्स्ट्रक्टर को बुलाया जा सकता है, और स्थिर कन्स्ट्रक्टर के नाम से पहले कहा जाता है।
  • इस मानचित्रण को उदाहरण कन्स्ट्रक्टर में भरना

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

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

विधि का उपयोग करें

 Enum.GetName(Type MyEnumType, object enumvariable) 

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

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

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

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

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

दस्तावेज यहां है:

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

… और अगर आप पास्कल मामले में अपने एंसम नाम (जैसा कि मैं करता हूं – जैसे आईआईएमएमएएनम वैल्यू = 1 इत्यादि), तो आप दोस्ताना फॉर्म को मुद्रित करने के लिए एक बहुत सरल रीजक्स का इस्तेमाल कर सकते हैं:

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

जिसे आसानी से किसी भी स्ट्रिंग से कहा जा सकता है:

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

आउटपुट:

मैरीले केस के लिए मेरी पागल पास्कल केस वाक्य कन्वर्ट

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

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

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

फिर आप इसे आसानी से अपनी एन्यूम उदाहरण से आसानी से देख सकते हैं:

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

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

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

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

आप हालांकि विस्तार तरीकों को लिख सकते हैं:

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

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


सी # 6 अद्यतन

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

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

 nameof(AuthenticationMethod.FORMS) == "FORMS" 

परंतु…

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

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

 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" मिल जाएगा।

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

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

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

 any.Tomato.ToString(); 

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

 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 के लिए पूरा करता है, जहां आपको "दोस्ताना नाम" की आवश्यकता नहीं होती है और केवल वापस लौटाएगा।

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

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

तो आपको Jakub Šturc के उत्तर के सभी लाभ मिलते हैं, इसके साथ ही हम इसका उपयोग एक स्विच स्टेटमेंट के साथ कर सकते हैं:

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

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

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

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

 MyStatus.Active.ToString("f"); 

या

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

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

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

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

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

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

}

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

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

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

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

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

इसलिए मैंने तय किया कि मैं एक 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 } 

मैं इसे कैसे विस्तार विधि के रूप में हल करता हूं:

 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.OrderType.GetDescription() 

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

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

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

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

आप एक ही वाक्यविन्यास का उपयोग करने के लिए enum के रूप में कर सकते हैं

 if (bla == AuthenticationMethod.FORMS) 

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

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

  • क्या मेरे नाम के नाम इस उद्देश्य के लिए पर्याप्त रूप से अनुकूल हैं, या मुझे मित्रता प्रदान करने की आवश्यकता है?
  • क्या मुझे गोल यात्रा की आवश्यकता है? यही है, क्या मुझे पाठ मूल्यों को लेना होगा और उन्हें इनम मूल्यों में पार्स करना होगा?
  • क्या यह मुझे अपनी परियोजना में कई ईमानों के लिए करना है, या सिर्फ एक ही है?
  • मैं किस प्रकार की UI तत्वों को इस जानकारी को प्रस्तुत कर रहा हूं – विशेष रूप से, क्या मैं UI को बाध्य करूँगा, या गुण पत्रक का उपयोग करूँगा?
  • क्या इसका स्थानीयकरण होना चाहिए?

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

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

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

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

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

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

  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; 

विकल्प 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"); } } 

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

Jakub Šturc's type-safe enum pattern is the best option I see here.

Look at it:

  • It has a private constructor so only the class itself can define the allowed values.
  • It is a sealed class so values can't be modifed through inheritence.
  • It is type-safe, allowing your methods to require only that type.
  • There is no reflection performance hit incurred by accessing the values.
  • And lastly, it can be modified to associate more than two fields together, for example a Name, Description, and a numeric Value.

My variant

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

Code looks a bit ugly, but usages of this struct are pretty presentative.

 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 

Also, I think, if a lot of such enums required, code generation (eg T4) might be used.

for me, the pragmatic approach is class inside class, sample:

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

Here is yet another way to accomplish the task of associating strings with enums:

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

This method is called like this:

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

You can group related enums in their own struct. Since this method uses the enum type, you can use Intellisense to display the list of enums when making the GetString() call.

You can optionally use the new operator on the DATABASE struct. Not using it means the strings List is not allocated until the first GetString() call is made.

If I'm understanding you correctly, you can simply use .ToString() to retrieve the name of the enum from the value (Assuming it's already cast as the Enum); If you had the naked int (lets say from a database or something) you can first cast it to the enum. Both methods below will get you the enum name.

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

Keep in mind though, the second technique assumes you are using ints and your index is 1 based (not 0 based). The function GetNames also is quite heavy by comparison, you are generating a whole array each time it's called. As you can see in the first technique, .ToString() is actually called implicitly. Both of these are already mentioned in the answers of course, I'm just trying to clarify the differences between them.

old post but…

The answer to this may actually be very simple. Use Enum.ToString() function

There are 6 overloads of this function, you can use Enum.Tostring("F") or Enum.ToString() to return the string value. No need to bother with anything else. Here is a working Demo

Note that this solution may not work for all compilers ( this demo does not work as expected ) but at least it works for the latest compiler.

based on the MSDN: http://msdn.microsoft.com/en-us/library/cc138362.aspx

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

str will be the names of the fields

Well, after reading all of the above I feel that the guys have over complicated the issue of transforming enumerators into strings. I liked the idea of having attributes over enumerated fields but i think that attributes are mainly used for Meta-data, but in your case i think that all you need is some sort of localization.

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

Now if we try to call the above method we can call it this way

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

All you need to do is just create a resource file containing all the enumerator values and the corresponding strings

Resource Name Resource Value
Color_Red My String Color in Red
Color_Blue Blueeey
Color_Green Hulk Color

What is actually very nice about that is that it will be very helpful if you need your application to be localized, since all you need to do is just create another resource file with your new language! and Voe-la!

When I am in a situation like that I propose the solution below.

And as a consuming class you could have

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

And using a bidirectional dictionary: Based on this ( https://stackoverflow.com/a/255638/986160 ) assuming that the keys will be associated with single values in the dictionary and similar to ( https://stackoverflow.com/a/255630/986160 ) but a bit more elegant. This dictionary is also enumerable and you can go back and forth from ints to strings. Also you don't have to have any string in your codebase with the exception of this class.

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

A lot of great answers here but in my case did not solve what I wanted out of an "string enum", which was:

  1. Usable in a switch statement eg switch(myEnum)
  2. Can be used in function parameters eg foo(myEnum type)
  3. Can be referenced eg myEnum.FirstElement
  4. I can use strings eg foo("FirstElement") == foo(myEnum.FirstElement)

1,2 & 4 can actually be solved with a C# Typedef of a string (since strings are switchable in c#)

3 can be solved by static const strings. So if you have the same needs, this is the simplest approach:

 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 } 

This allows for example:

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

तथा

 public TypeObject CreateType(Types type) { switch (type) { case Types.ImageType: // break; case Types.DataType: // break; } } 

Where CreateType can be called with a string or a type. However the downside is that any string is automatically a valid enum , this could be modified but then it would require some kind of init function…or possibly make they explicit cast internal?

Now if an int value was important to you (perhaps for comparison speed), you could use some ideas from Jakub Šturc fantastic answer and do something a bit crazy, this is my stab at it:

  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 } 

but of course "Types bob = 4;" would be meaningless unless you had initialized them first which would sort of defeat the point…

But in theory TypeA == TypeB would be quicker…

Use object Enum.Parse(System.Type enumType, string value, bool ignoreCase); got it from http://blogs.msdn.com/b/tims/archive/2004/04/02/106310.aspx

My answer, working on @user29964 's answer (which is by far the simplest and closest to a Enum) is

  public class StringValue : System.Attribute { private string _value; public StringValue(string value) { _value = value; } public string Value { get { return _value; } } public static string GetStringValue(Enum Flagvalue) { Type type = Flagvalue.GetType(); string[] flags = Flagvalue.ToString().Split(',').Select(x => x.Trim()).ToArray(); List<string> values = new List<string>(); for (int i = 0; i < flags.Length; i++) { FieldInfo fi = type.GetField(flags[i].ToString()); StringValue[] attrs = fi.GetCustomAttributes(typeof(StringValue), false) as StringValue[]; if (attrs.Length > 0) { values.Add(attrs[0].Value); } } return String.Join(",", values); } 

प्रयोग

 [Flags] public enum CompeteMetric { /// <summary> /// u /// </summary> [StringValue("u")]//Json mapping Basic_UniqueVisitors = 1 //Basic , /// <summary> /// vi /// </summary> [StringValue("vi")]//json mapping Basic_Visits = 2// Basic , /// <summary> /// rank /// </summary> [StringValue("rank")]//json mapping Basic_Rank = 4//Basic } 

उदाहरण

  CompeteMetric metrics = CompeteMetric.Basic_Visits | CompeteMetric.Basic_Rank; string strmetrics = StringValue.GetStringValue(metrics); 

this will return "vi,rank"