सी # 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;
एक आकर्षण की तरह काम करता है, धन्यवाद! अजीब बात है कि आप एक enum परिभाषित कर सकते हैं: "सार्वजनिक enum MyEnum: int {...}" और इसके मूल्यों को पूरी तरह से जाति नहीं है। वहां "जेनेरिक एनम" की कोई अवधारणा नहीं है? - सार्वजनिक enum MyEnum - या यह पूरी तरह हास्यास्पद है? –
Pwninstein
आप अपने enum "सार्वजनिक enum ReturnValue: int" पर डेलकेयर प्रकार कर सकते हैं जो लागू करता है कि मान प्रकार int हैं। यह अभी भी अंतर्निहित कास्टिंग प्रदान नहीं करता है। यह दिखाने के लिए संपादन करना कि यह enum_ enum में मूल्यों का उपयोग करने के लिए एक अच्छा विचार है। –
एक मामूली सुझाव - यदि आपके मूल्य भविष्य के संस्करणों में बदलते हैं तो 'const' की बजाय' स्थिर रीडोनली int' का उपयोग करें। आप नहीं चाहते कि कॉलर्स के पास उनके कोड में संकलित मूल्य हो। –