2008-12-09 2 views
9

सी # में enums के साथ मज़ा। एक सामान्य सूची लें जिसे कुछ एनम स्टोर करने के लिए बनाया गया है जिसे आपने पहले परिभाषित किया था और इसमें कुछ आइटम जोड़े थे। Foreach या GetEnumerator<T>() के साथ Iterate लेकिन मूल तो कुछ अन्य enum निर्दिष्ट करें और देखें कि क्या होता है। मैं अमान्यकास्टएक्सप्शन या ऐसा कुछ करने की उम्मीद कर रहा था लेकिन यह पूरी तरह से काम करता है :)। कारें और पशु: क्या एनम्स केवल पूर्णांक, प्रकार या दोनों का नाम नहीं है?

public enum Cars 
    { 
     Honda = 0, 
     Toyota = 1, 
     Chevrolet = 2 
    } 
    public enum Animals 
    { 
     Dog = 0, 
     Cat = 1, 
     Tiger = 2 
    } 

और मुख्य विधि में ऐसा करते हैं:

public static void Main() 
    { 
     List<Cars> cars = new List<Cars>(); 
     List<Animals> animals = new List<Animals>(); 
     cars.Add(Cars.Chevrolet); 
     cars.Add(Cars.Honda); 
     cars.Add(Cars.Toyota); 

     foreach (Animals isItACar in cars) 
     { 
      Console.WriteLine(isItACar.ToString()); 
     } 
     Console.ReadLine(); 
    } 

यह इस प्रिंट होगा

उदाहरण के लिए के लिए एक सरल सांत्वना आवेदन लेने के लिए और वहाँ दो enums बना सकते हैं कंसोल में:

Tiger 
Dog 
Cat 

ऐसा क्यों हो रहा है? मेरा पहला अनुमान यह था कि enum वास्तव में एक प्रकार नहीं है, यह सिर्फ और int है लेकिन यह सच नहीं है: अगर हम लिखते हैं:

Console.WriteLine(Animals.Tiger.GetType().FullName); हम उसका पूर्ण योग्य नाम मुद्रित करेंगे! तो यह क्यों?

उत्तर

21

एनम प्रकार अलग हैं, लेकिन आप एक अंतर्निहित कलाकार द्वारा भ्रमित हो रहे हैं जो foreach में है।

public static void Main() 
{ 
    List<Cars> cars = new List<Cars>(); 
    List<Animals> animals = new List<Animals>(); 
    cars.Add(Cars.Chevrolet); 
    cars.Add(Cars.Honda); 
    cars.Add(Cars.Toyota); 

    foreach (Cars value in cars) 
    { 
     // This time the cast is explicit. 
     Animals isItACar = (Animals) value; 
     Console.WriteLine(isItACar.ToString()); 
    } 
    Console.ReadLine(); 
} 

अब परिणाम आश्चर्य आप करता है:

के अपने पाश थोड़ा पुनर्लेखन करते हैं? उम्मीद है कि, संभवतः इस तथ्य को छोड़कर कि आप एक enum से दूसरे में डाले जा सकते हैं। यह आपका मूल कोड क्या कर रहा है इसका एक और स्पष्ट संस्करण है।

तथ्य यह है कि प्रत्येक foreach लूप (हालांकि यह आमतौर पर नो-ऑप होता है) में एक कास्ट अंतर्निहित है, जो कि अधिकांश डेवलपर्स भ्रमित हो जाएंगे, मुझे लगता है।

सी # 3.0 कल्पना की धारा 8.8.4 से:

ऊपर के चरणों, अगर सफल, स्पष्ट रूप से एक संग्रह प्रकार सी, प्रगणक प्रकार ई और तत्व प्रकार टी का उत्पादन प्रपत्र की एक foreach बयान

foreach (V v in x) embedded-statement 

तो विस्तार किया जाता है करने के लिए:

{ 
    E e = ((C)(x)).GetEnumerator(); 
    try { 
     V v; 
     while (e.MoveNext()) { 
      v = (V)(T)e.Current; 
      embedded-statement 
     } 
    } 
    finally { 
     ... // Dispose e 
    } 
} 

गणन रूपांतरण ही खंड 6.2.2 में कवर किया जाता है:

स्पष्ट गणना रूपांतरण हैं:

  • sbyte, बाइट, लघु, ushort, पूर्णांक, uint, लंबे, Ulong, चार, नाव, डबल, या दशमलव किसी भी enum प्रकार के लिए से।
  • किसी भी enum-type से sbyte, बाइट, शॉर्ट, ushort, int, uint, long, ulong, char, float, double, या दशमलव से।
  • किसी भी enum-type से किसी अन्य enum-type तक।

एक स्पष्ट गणन रूपांतरण दोनों के बीच प्रकार कि enum प्रकार के अंतर्निहित प्रकार के रूप में किसी भी भाग लेने enum प्रकार इलाज है, और फिर एक अस्पष्ट या स्पष्ट संख्यात्मक के बीच रूपांतरण प्रदर्शन से संसाधित किया जाता है परिणामस्वरूप प्रकार। उदाहरण के लिए, एक enum-type ई के साथ अंतर्निहित प्रकार के int, अंतर्निहित ई से बाइट में रूपांतरण को एक स्पष्ट संख्यात्मक रूपांतरण (§6.2.1) से int से बाइट तक संसाधित किया जाता है, और बाइट से रूपांतरण ई को को बाइट से int तक एक अंतर्निहित संख्यात्मक रूपांतरण (§6.1.2) के रूप में संसाधित किया जाता है।

+1

हाँ बहुत अच्छा जवाब। मुझे अब एहसास है कि किसी भी प्रकार के enums के बीच स्पष्ट कास्ट विफल नहीं होगा क्योंकि वे व्यावहारिक रूप से एक पूर्णांक हैं, और समस्या की जड़ थी। – Aleksandar

2

संकल्पनात्मक रूप से, एक एनम एक स्ट्रिंग प्रतिनिधित्व और एक संख्या के साथ एक सांख्यिकीय रूप से टाइप किया गया मान है। जब आप enum पर ToString() पर कॉल करते हैं, तो यह स्ट्रिंग प्रस्तुति वापस कर देगा। जब आप enum पर GetType() पर कॉल करते हैं, तो आपको स्थिर गणना प्रकार मिल जाएगा। यदि आपने int पर एक enum डाला है, तो आपको enum के लिए पूर्णांक मान मिलेगा।

Enums को दृढ़ता से टाइप किया जाना चाहिए, लेकिन ऐसी कुछ चीजें हैं जिन्हें आपको जागरूक करने की आवश्यकता है, इस तथ्य की तरह कि किसी भी पूर्णांक को किसी भी enum पर डाला जा सकता है भले ही उसके पास कोई घोषणा नहीं है (इस मामले में स्ट्रिंग का प्रतिनिधित्व संख्या के समान होगा)।

सीएलआर में, एनम्स (जैसे bool एस) को सिर्फ int एस के रूप में माना जाता है, लेकिन अगर आप GetType() या GetString() कहलाते हैं तो यह उन संस्करणों को कॉल करता है जो उपरोक्त वर्णित हैं।

0

आप एक विशिष्ट प्रकार से एक enum भी प्राप्त कर सकते हैं।

public enum Cats : byte { ... } 
public enum Dogs : int { ... }