2012-09-16 9 views
5

इस तरह एक enum को देखते हुए:मैं जेनिक्स का उपयोग एनम से एक आईनेमरेबल बनाने का तरीका बनाने के लिए कैसे कर सकता हूं?

public enum City { 
    London = 1, 
    Liverpool = 20, 
    Leeds  = 25 
} 

public enum House { 
    OneFloor = 1, 
    TwoFloors = 2 
} 

मैं मेरे एक IEnumerable देने के लिए निम्नलिखित कोड का उपयोग कर रहा:

City[] values = (City[])Enum.GetValues(typeof(City)); 
var valuesWithNames = from value in values      
    select new { value = (int)value, name = value.ToString() }; 

कोड बहुत अच्छा काम करता है लेकिन मैं काफी का एक बहुत के लिए यह करने के लिए है enums। क्या ऐसा कोई तरीका है जिससे मैं ऐसा करने का एक सामान्य तरीका बना सकता हूं?

+1

समस्या यह है कि सी # जेनेरिक प्रकारों पर 'enum' बाधाओं की अनुमति नहीं देता है। आप जॉन स्कीट की [अनियंत्रित मेलोडी] (http://code.google.com/p/unconstrained-melody/) का उपयोग कर सकते हैं। – Adam

+0

यदि आपको केवल रनटाइम पर 'IENumerable' की आवश्यकता है तो आप प्रतिबिंब का उपयोग कर सकते हैं। अन्यथा आप [templating] (http://msdn.microsoft.com/en-us/library/bb126445.aspx) और प्रतिबिंब का उपयोग करने पर विचार कर सकते हैं। – Guillaume

उत्तर

1

इस समारोह आप मदद कर सकते हैं:

public static IEnumerable<KeyValuePair<int, string>> GetValues<T>() where T : struct 
{ 
     var t = typeof(T); 
     if(!t.IsEnum) 
      throw new ArgumentException("Not an enum type"); 

     return Enum.GetValues(t).Cast<T>().Select (x => 
       new KeyValuePair<int, string>(
        (int)Enum.ToObject(t, x), 
        x.ToString())); 
} 

उपयोग:

var values = GetValues<City>(); 
+0

'InvalidOperationException' को * * के रूप में परिभाषित किया गया है जब ऑब्जेक्ट की वर्तमान स्थिति के लिए विधि कॉल अमान्य होने पर अपवाद को फेंक दिया जाता है।"* यह फेंकने के लिए वास्तव में भ्रामक अपवाद की तरह प्रतीत होता है। – Adam

+0

@codesparkle शायद। मैंने इसे 'ArgumentException' – Magnus

+0

में बदल दिया है * एक' टाइपअर्ग्यूमेंट एक्सेप्शन 'जैसा कि * UnconstrainedMelody * में परिभाषित एक आदर्श होगा। निकटतम फिटिंग पूर्वनिर्धारित अपवाद शायद 'ArgumentException' हालांकि * (" अपवाद जिसे फेंक दिया गया है जब किसी विधि को प्रदान किए गए तर्कों में से एक मान्य नहीं है। ") * – Adam

1

क्यों नहीं:

IEnumerable<object> GetValues<T>() 
    { 
     return Enum.GetValues(typeof (T)) 
        .Cast<T>() 
        .Select(value => new {  
              value = Convert.ToInt32(value), 
              name = value.ToString() 
             }); 

    } 

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

var result = GetValues<City>(); 

आप बाधा सामान्य Tenum के रूप में बनाने के लिए चाहते हैं, तो क्योंकि enumसामान्य contraint सीधे के रूप में इस्तेमाल नहीं किया जा सकता, लेकिन enum इंटरफ़ेस IConvertible से विरासत में विश्वास करता है, इस तरह विश्वास करें ठीक है:

IEnumerable<object> GetValues<T>() where T: struct, IConvertible 
{} 

Dictionary द्वारा IEnumerable<object> प्रतिस्थापित करने के लिए:

Dictionary<int, string> GetValues<T>() where T : struct, IConvertible 
{ 
    return Enum.GetValues(typeof (T)).Cast<T>() 
       .ToDictionary(value => Convert.ToInt32(value), 
          value => value.ToString()); 
} 

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

+0

मुझे एक शब्दकोश लौटने के साथ दो समस्याएं दिखाई देती हैं: सबसे पहले यह अनियंत्रित है। दूसरा यह एक शब्दकोश को वापस करने के लिए अनावश्यक लगता है अगर यह लुकअप के लिए इस्तेमाल नहीं किया जा रहा है। – Magnus

+0

@ मैग्नस: अनियंत्रित के साथ सच है, मैं क्यों उपयोग करता हूं शब्दकोश है Immerable की तुलना में मजबूत प्रकार है। –

3

उपयोग जॉन स्कीट के unconstrained melody

using UnconstrainedMelody; 

आप एक Dictionary<int, string> में अपने enum मान डाल सकते हैं और फिर उन पर गणना:

var valuesAsDictionary = Enums.GetValues<City>() 
           .ToDictionary(key => (int)key, value => value.ToString()); 

लेकिन आप शायद भी ऐसा करने की जरूरत नहीं है। क्यों न सिर्फ मूल्यों पर गणना करें:

foreach (var value in Enums.GetValues<City>()) 
{ 
    Console.WriteLine("{0}: {1}", (int)value, value); 
} 
+0

आप' int' क्यों नहीं कर रहे हैं और 'टी' नहीं? Enums को इन्ट्स नहीं होना चाहिए , और कोई कारण नहीं है कि आप 'शब्दकोश ' को वापस नहीं कर सकते हैं। – Lee

+1

@Lee प्रश्न में वह स्पष्ट रूप से int और स्ट्रिंग चाहता है। – Magnus

+0

@Lee लेकिन फिर फिर, एक शब्दकोश क्यों बनाएं जब आपको आवश्यक सभी जानकारी मौजूद हो enum मूल्य के भीतर ही? यह वह बिंदु है जिसे मैंने अपने उत्तर के दूसरे भाग में व्यक्त करने की कोशिश की। – Adam

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

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