c# मैं कैसे एक निरंतर के रूप में enums की संख्या प्राप्त कर सकते हैं?




unity3d const (4)

एंटम में परिभाषित मदों की कुल संख्या से , मुझे लगता है कि मैं इन्हें उपयोग करके संख्याओं की संख्या प्राप्त कर सकता हूं:

Enum.GetNames(typeof(Item.Type)).Length;

बहुत अच्छा काम करता है!

लेकिन, मुझे इस संख्या को एक निरंतर संख्या के रूप में चाहिए, ताकि मैं इसे एकता की [Range(int, int)] सुविधा में इस्तेमाल कर [Range(int, int)]

private const int constEnumCount = Enum.GetNames(typeof(Item.Type)).Length;

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

मैं कैसे एक निरंतर के रूप में enums की संख्या प्राप्त कर सकते हैं?


सी # में, एक const को निरंतर के रूप में परिभाषित किया जाता है, अर्थात् मूल्य (यह गणना नहीं करता है!) संकलित विधानसभा में सीधे एम्बेडेड है

आपको समस्याग्रस्त कुछ करने से रोकने के लिए, संकलक आपको किसी गणना के परिणाम को असाइन करने के लिए अनुमति नहीं देता है। समझने के लिए क्यों, यह संभव था:

A.dll
  public enum Foo { A, B }

B.dll
  public const NumberOfFoos = Enum.GetNames(typeof(Foo)).Length;

// Compiles to:
B.dll
  public const NumberOfFoos = 2;

अब आप A.dll को बदलते हैं:

A.dll
  public enum Foo { A, B, C, D }

B.dll
      public const NumberOfFoos = 2; // Oh no!

तो आपको सही मूल्य प्राप्त करने के लिए B.dll को पुनः कंपाइल करने की आवश्यकता होगी।

यह खराब हो जाता है: कल्पना कीजिए कि आपके पास एक सीडीएलएल है, जो बी। नम्बरऑफ़फूओज़ का उपयोग करता है। मान 2 को सीधे सीडीएलएल में एम्बेडेड किया जाएगा, इसलिए इसे सही मूल्य प्राप्त करने के लिए, B.dll के बाद पुनः कंपाइल करने की आवश्यकता होगी। इसलिए (सफलता का गड्ढा), सी # आपको const को उस असाइनमेंट को करने की अनुमति नहीं देता है


मान लें कि आपको एक const आवश्यकता है क्योंकि आप एट्रिब्यूट ( यह एक ?) के लिए मान निर्दिष्ट करने की कोशिश कर रहे हैं, तो आप भाग्य से बाहर हैं

आपके विकल्प हैं:

  1. विशेषता घोषणा में गिनती या खुद को एक const रूप में const और गणना की गणना के साथ गिनती को रखने के लिए सावधान रहना
  2. आपके लिए विशेषता डालने के लिए PostSharp या कुछ अन्य पहलू उन्मुख ढांचे का उपयोग करें मैंने खुद कभी ऐसा नहीं किया है, लेकिन यह संभव है ( कैसे एक PostSharp विशेषता का उपयोग कर एक विशेषता इंजेक्षन? )

संभवतः आप टी 4 टेम्पलेट्स के साथ ऐसा कुछ भी कर सकते हैं, लेकिन इससे ज़्यादा कूड़ी मिलेगी।

क्या यह बात थी, जब तक आप बात नहीं कर रहे हैं, लेकिन सैकड़ों विभिन्न गणनाओं के सेट में, मैं लंबाई को कठिन कूट कर लेता हूं और मुझे यह कहें कि मुझे इसकी ज़रूरत कहाँ थी।

// WARNING - if you add members update impacted Range attributes
public enum MyEnum
{
    foo,
    bar,
    baz
}

[Range(0, 3)]
class Test
{
    public Test()
    {
        int enumCount = Enum.GetNames(typeof(MyEnum)).Length;
        int rangeMax = GetType().GetCustomAttributes(typeof(Range), false).OfType<Range>().First().Max;

        Debug.Assert(enumCount == rangeMax);
    }
    static void Main(string[] args)
    {
        var test = new Test();
    }
}

दुर्भाग्यवश, तकनीकी सीमाओं के कारण किसी भी सार्थक तरीके से करना संभव नहीं है:

  • [Range(int,int)] एक विशेषता है, और एक विशेषता के लिए प्रदान की जाने वाली सभी जानकारी एक const है
  • Enum.GetValues(typeof(MyEnum)).Length में मानों की संख्या प्राप्त करने के लिए केवल वास्तविक बुलेटप्रूफ तरीका है Enum.GetValues(typeof(MyEnum)).Length या Enum.GetNames(typeof(MyEnum)).Length , दोनों जिनमें समय प्रतिबिंब होता है

हालांकि, ऐसे हैंक्स जो काम की तरह हो सकते हैं उदाहरण के लिए, एक एन्यूएम का मान एक पूर्णांक को डाली जा सकता है। जब तक कोई आपके मानों के लिए स्पष्ट रूप से परिभाषित नहीं होता है, तब तक आप इस प्रकार के अंतिम तत्व का उपयोग अपनी तरह से कर सकते हैं:

[Range(0,(int)MyEnum.LastValue)]
public void BlahBlahBlah() {}

हालांकि, यह जान लें कि जैसे ही कोई इंम्यूलेशन में किसी नए प्रविष्टि को जोड़ता है, जैसे कि आप enum में तत्वों का उपयोग कर रहे हैं या फिर पुनः लोड करते हैं, आपका कोड अप्रत्याशित रूप से टूट जाएगा और आप की तरह व्यवहार नहीं करेगा।

यह उदास है, लेकिन सी # संकलक जावा, सी, और सी + + कंपाइलर जैसे संकलक में साधारण गणित करने के लिए पर्याप्त स्मार्ट नहीं है तो यहां तक ​​कि मैंने जो भी उदाहरण दिया था, वह वास्तव में वास्तव में काम करेगा अगर LastValue का उपयोग किसी भी चीज़ के लिए नहीं किया गया था, जो कि आखिरी तत्व को enum में चिह्नित करता है यह सी # संकलक की जटिलता को कम करता है, जो आपके एप्लिकेशन के लिए संकलन की गति को भी बेहतर बनाता है। जैसे, कुछ ट्रेड-ऑफ हैं जो सी # और सीएलआर टीम ने अन्य स्थानों पर अपने अनुभव को बेहतर बनाने में कामयाबी हासिल की।


आप रनटाइम पर const पर असाइन नहीं कर सकते / बना सकते हैं आप ऐसा करने की कोशिश कर रहे हैं एक संकलन का संकलन समय पर पूरी तरह से मूल्यांकन किया जाना चाहिए, रनटाइम नहीं।

मुझे एकता के बारे में निश्चित नहीं है (और क्यों यह एक const आवश्यकता है) , लेकिन मैं readonly लिए उपयोग की तलाश करेंगे

private readonly int constEnumCount = Enum.GetNames(typeof(Item.Type)).Length;






constants