2009-02-23 7 views
27

अगर मैं निम्नलिखित enum है:क्या मैं इसका उपयोग करने या वापस करने का प्रयास करते समय एनम मूल्य कास्टिंग करने से बच सकता हूं?

public enum ReturnValue{ 
    Success = 0, 
    FailReason1 = 1, 
    FailReason2 = 2 
    //Etc... 
} 

मैं कास्टिंग से बचने कर सकते हैं जब मैं लौटने के लिए, इस तरह:

public static int main(string[] args){ 
    return (int)ReturnValue.Success; 
} 

यदि नहीं, तो क्यों डिफ़ॉल्ट रूप से एक पूर्णांक के रूप में इलाज एक enum मान नहीं है ?

उत्तर

46

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

public static class ReturnValue 
{ 
    public const int Success = 0; 
    public const int FailReason1 = 1; 
    public const int FailReason2 = 2; 
    //Etc... 
} 

आप यह कर देता है कि: आप मुख्य रूप से निरंतर मूल्यों के भंडारण के लिए enum उपयोग करते हैं, एक स्थिर वर्ग उपयोग करने पर विचार।

public static int main(string[] args){ 
    return ReturnValue.Success; 
} 

संपादित

जब आप एक enum करने के लिए मान प्रदान करना चाहते हैं है जब आप उन्हें गठबंधन करने के लिए चाहते हैं। नीचे उदाहरण देखें:

[Flags] // indicates bitwise operations occur on this enum 
public enum DaysOfWeek : byte // byte type to limit size 
{ 
    Sunday = 1, 
    Monday = 2, 
    Tuesday = 4, 
    Wednesday = 8, 
    Thursday = 16, 
    Friday = 32, 
    Saturday = 64, 
    Weekend = Sunday | Saturday, 
    Weekdays = Monday | Tuesday | Wednesday | Thursday | Friday 
} 

इस enum को फिर bitwise गणित का उपयोग करके उपभोग किया जा सकता है। कुछ अनुप्रयोगों के लिए नीचे उदाहरण देखें। enum अंतर्निहित प्रकार के रूप में पूर्णांक उपयोग करने के लिए नहीं है क्योंकि

public static class DaysOfWeekEvaluator 
{ 
    public static bool IsWeekends(DaysOfWeek days) 
    { 
     return (days & DaysOfWeek.Weekend) == DaysOfWeek.Weekend; 
    } 

    public static bool IsAllWeekdays(DaysOfWeek days) 
    { 
     return (days & DaysOfWeek.Weekdays) == DaysOfWeek.Weekdays; 
    } 

    public static bool HasWeekdays(DaysOfWeek days) 
    { 
     return ((int) (days & DaysOfWeek.Weekdays)) > 0; 
    } 

    public static bool HasWeekendDays(DaysOfWeek days) 
    { 
     return ((int) (days & DaysOfWeek.Weekend)) > 0; 
    } 
} 
+0

एक आकर्षण की तरह काम करता है, धन्यवाद! अजीब बात है कि आप एक enum परिभाषित कर सकते हैं: "सार्वजनिक enum MyEnum: int {...}" और इसके मूल्यों को पूरी तरह से जाति नहीं है। वहां "जेनेरिक एनम" की कोई अवधारणा नहीं है? - सार्वजनिक enum MyEnum - या यह पूरी तरह हास्यास्पद है? – Pwninstein

+0

आप अपने enum "सार्वजनिक enum ReturnValue: int" पर डेलकेयर प्रकार कर सकते हैं जो लागू करता है कि मान प्रकार int हैं। यह अभी भी अंतर्निहित कास्टिंग प्रदान नहीं करता है। यह दिखाने के लिए संपादन करना कि यह enum_ enum में मूल्यों का उपयोग करने के लिए एक अच्छा विचार है। –

+2

एक मामूली सुझाव - यदि आपके मूल्य भविष्य के संस्करणों में बदलते हैं तो 'const' की बजाय' स्थिर रीडोनली int' का उपयोग करें। आप नहीं चाहते कि कॉलर्स के पास उनके कोड में संकलित मूल्य हो। –

2

एनम्स और इनट्स बस spec के अनुसार पूरी तरह से जाली नहीं हैं (शाब्दिक 0 को छोड़कर, जिसे तुलना परीक्षण/असाइनमेंट/आदि के लिए अनुमति दी जाती है)। हालांकि, स्पष्ट कलाकारों की जरूरत है।

+2

(कल्पना 13.1.3 और ECMA 334v4 की 13.2.2) –

+0

यह अच्छा होगा यदि आप enums –

+0

के लिए समानता ऑपरेटर रद्द कर सकते थे @Chris आप एक विस्तार विधि लिख सकता है हो जाएगा शायद,। काफी समान नहीं है, लेकिन ... –

0

नहीं, आप कास्टिंग से बच नहीं सकते हैं; क्यों कोई अंतर्निहित रूपांतरण नहीं है, मुझे नहीं पता, लेकिन ऐसा नहीं है।

4

कोई अंतर्निहित ढला होता है। यदि आपका enum अंतर्निहित प्रकार के रूप में एक यूंट का उपयोग करता है, उदाहरण के लिए, यूंट से int तक कोई अंतर्निहित कलाकार नहीं है।

+1

दो अपवॉट प्रोग्राम नहीं किए हैं? मुझे यह जवाब अनुपयोगी लगता है कि यह उस प्रश्न का उत्तर देता है जो लिखा गया था, लेकिन स्पष्ट प्रश्न नहीं पूछा जा रहा था। क्या होगा यदि आप 'enum MyEnum: int {} '? परिभाषित करते हैं; तो यह करने की ज़रूरत नहीं है, लेकिन प्रभावी रूप से अंतर्निहित प्रकार के रूप में int का उपयोग करता है; और अभी भी कोई अंतर्निहित कास्टिंग नहीं है। sadpanda :( – ANeves

0

आश्चर्यजनक रूप से पर्याप्त, यह .NET Framework के लिए विशिष्ट नहीं है, बल्कि केवल सी # के लिए विशिष्ट नहीं है। जैसा कि अन्य टिप्पणीकार पहले ही बता चुके हैं, सी # में यह मूल रूप से भाषा का एक विनिर्देश है। वीबी.नेट में भी यह सच नहीं है।

Enums in VB.NET के लिए एमएसडीएन संदर्भ पृष्ठ देखें। ध्यान दें कि आप Enum घोषणा समय पर एक गणित के डेटा प्रकार निर्दिष्ट कर सकते हैं।

इसका मतलब है कि, अगर आप वास्तव में नहीं कूड़े को (पूर्णांक) के लिए डाले के साथ अपने कोड चाहते हैं, तो आप अपने गणना VB.NET में, लिख सकता है एक पूर्णांक के रूप में यह घोषणा करते हैं, तो का उपयोग करें कि Enum सी से #।

याद रखें कि उन्होंने हमें कैसे बताया कि कंप्यूटर हमारे जीवन को इतना आसान बना देंगे? :)

+0

आप यहां एक ही समस्या में भाग लेंगे, क्योंकि आप सी # में enum का उपभोग कर रहे हैं, और याद रखें, सी # निहित रूप से enum परिवर्तित नहीं कर सकता! आप वापस वर्ग में हैं;) –

0

आप नामांकन स्थिरांक का एक सेट बनाने के लिए गणना को बनाने के पीछे मूल उद्देश्य के लिए इस व्यवहार को लिख सकते हैं जो अंतर्निहित प्रकार के आधार पर निर्दिष्ट (या डिफ़ॉल्ट) मान हो सकता है।

के रूप में अपने प्रश्न से संबंधित वहाँ दो अलग-अलग मुद्दों पर विचार करने के लिए कर रहे हैं:

  1. एक Enum मूल्य डिफ़ॉल्ट रूप से एक पूर्णांक के रूप में नहीं माना जा सकता क्योंकि तब आप और प्रदान करने के लिए किसी भी पूर्णांक में सक्षम हो जाएगा वहाँ यह पुष्टि करने के लिए कोई संकलित समय जांच नहीं होगी कि प्रदत्त पूर्णांक वास्तव में गणना में मूल्य के रूप में मौजूद है।

  2. कास्टिंग, आवश्यक के बाद से आप अंतर्निहित प्रकार के, यानी, int या byte (प्रकार YourCustomEnum जो System.Enum वर्ग से निकला का) शासी प्रकार से परिवर्तित करने के लिए कोशिश कर रहे हैं हो जाता है आदि

4

सी # enum बेकार है।

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

  • अपने प्रकार से एक सामान्य int में परिवर्तित करने के लिए एक निहित ऑपरेटर प्रदान करें ताकि आपको कास्ट करने की आवश्यकता न हो। यदि पूर्णांक जैसे बाधा, पूरा करने में विफल
  • किसी पूर्णांक से अपने प्रकार है, जो एक त्रुटि फेंकता में परिवर्तित करने के लिए एक स्पष्ट ऑपरेटर प्रदान करें (int x) => (एक्स> = 0 & & एक्स < = 2)।

तो इस तकनीक का इस्तेमाल, एक सामान्य अपरिवर्तनीय वर्ग के आधार के रूप में ConstrainedNumber<T> है, जो एक निर्माता है कि बाधा के लिए एक टी मूल्य और प्रतिनिधि को स्वीकार करता है बनाने के लिए: delegate bool NumberConstraint<T>(T value)। कन्स्ट्रक्टर को बाधा प्रतिनिधि के माध्यम से मूल्य चलाना चाहिए, और अगर यह बाधा को पूरा करने में विफल रहता है तो अपवाद फेंकना चाहिए। बेस क्लास को टी में अंतर्निहित रूपांतरण ऑपरेशन का भी ख्याल रखना चाहिए, और वस्तु को अधिभारित करके समानता को संभालना चाहिए। एक्वाल्स (ऑब्जेक्ट) और ऑब्जेक्ट। गेटहाशकोड(), परिभाषित == और! = ConstrainedNumber<T> के लिए ऑपरेटर, और IEquatable<T> को कार्यान्वित करना और IEquatable<ConstrainedNumber<T>>। मैं बेस क्लास, और सभी व्युत्पन्न प्रकारों के लिए एक प्रतिलिपि निर्माता को परिभाषित करने की भी सिफारिश करता हूं। प्रतिबिंब के माध्यम से कॉपी कन्स्ट्रक्टर को पुनर्प्राप्त करके क्लोनिंग को बेस क्लास में साफ रूप से लागू किया जा सकता है, लेकिन यह पूरी तरह से वैकल्पिक है। आप ConstrainedNumber<T> स्वयं को कार्यान्वित कर सकते हैं, जब तक कि मैंने इसे पहले से ही स्टैक ओवरफ्लो पर पोस्ट नहीं किया है।

आप अपने व्युत्पन्न ConstrainedNumber में नामित स्थिर रीडोनली मान प्रदान कर सकते हैं, ताकि आप उन्हें एक enum की तरह एक्सेस कर सकें।

public sealed class ReturnValue: ConstrainedNumber<int> 
{ 
    public static readonly NumberConstraint<int> constraint = (int x) => (x >= 0 && x < 3); 

    public static readonly ReturnValue Success = new ReturnValue(0); 
    public static readonly ReturnValue FailReason1 = new ReturnValue(1); 
    public static readonly ReturnValue FailReason2 = new ReturnValue(2); 

    private ReturnValue(int value): base(value, constraint) {} 
    private ReturnValue(ReturnValue original): base (original) {} //may be used to support IClonable implementation in base class 
    public static explicit operator ReturnValue(int value) 
    { 
     switch(value) //switching to return an existing instance is more efficient than creating a new one and re-checking the constraint when there is a limited number of allowed values; if the constraint was more generic, such as an even number, then you would instead return a new instance here, and make your constructors public. 
     { 
      case 0: return Success; 
      case 1: return FailReason1; 
      case 2: return FailReason2; 
     } 
     throw new ArgumentException("Value fails to meet the constraint defined for " + typeof(ReturnValue).FullName + ".", "value"); 
    } 

} 

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

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

EvenNumber x = (EvenNumber)2; 
EvenNumber y = (EvenNumber)3; //throws exception "Value fails to meet the constraint defined for {namespace}.EvenNumber." A c# enum would stupidly allow such a cast, creating an invalid EvenNumber, breaking the object-oriented model 
int z = x; //implicit conversion, no cast necessary; 
-2

कैसे एक कक्षा के स्थिर सदस्यों का उपयोग कर के बारे में?

//enum DocInfos { DocName, DocNumber, DocVersion}; 
public class DocInfos 
{ 
    public static int DocName = 0; 
    public static int DocNumer = 1; 
    public static int DocVersion = 2; 
} 

...

  Doc = new string[DocInfos.DocVersion]; 
      // Treffer 
      Doc[DocInfos.DocName] = TrimB(HTMLLines[lineCounter + 2]) 

...

+0

बस FYI - मैंने इसे वोट नहीं दिया, लेकिन मुझे लगता है कि इसे बी/सी वोट दिया गया था, यह शीर्ष वोट वाले उत्तर और गलत दोनों के अनावश्यक है। कक्षा DocInfos स्थिर होना चाहिए। –

संबंधित मुद्दे

 संबंधित मुद्दे