Enum "वंशानुक्रम"


391

मेरे पास निम्न स्तर के नामस्थान में एक एनम है। मैं निम्न स्तर के एनम को "विरासत में मिला" मध्य स्तर के नामस्थान में एक वर्ग या एनम प्रदान करना चाहता हूं।

namespace low
{
   public enum base
   {
      x, y, z
   }
}

namespace mid
{
   public enum consume : low.base
   {
   }
}

मैं उम्मीद कर रहा हूं कि यह संभव है, या शायद किसी तरह का वर्ग जो एनम उपभोग की जगह ले सकता है जो एनम के लिए अमूर्तता की एक परत प्रदान करेगा, लेकिन फिर भी उस वर्ग के एक उदाहरण को एनम तक पहुंचने दें।

विचार?

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


जवाबों:


462

यह नहीं हो सकता। एनम अन्य एनम से विरासत में नहीं मिल सकते हैं। वास्तव में सभी एनमों को वास्तव में इनहेरिट करना चाहिए System.Enum। सी # सिंटैक्स को विरासत की तरह दिखने वाले एनम मूल्यों के अंतर्निहित प्रतिनिधित्व को बदलने की अनुमति देता है, लेकिन वास्तविकता में वे अभी भी System.enum से विरासत में प्राप्त करते हैं।

पूर्ण विवरण के लिए सीएलआई युक्ति का खंड 8.5.2 देखें। युक्ति से प्रासंगिक जानकारी

  • सभी एनम से प्राप्त होना चाहिए System.Enum
  • उपरोक्त के कारण, सभी एनम वैल्यू टाइप हैं और इसलिए सील किए जाते हैं

2
और सभी मूल्य प्रकार
System.ValueType

4
उल्लेख करना है कि @Seven का जवाब एक वैध
तरीका है

लेकिन @ स्टीवन का जवाब switchपरिस्थिति में इस्तेमाल नहीं किया जा सकता ।
जियोनी

@zionpi हाँ, लेकिन ध्यान दें कि (मुझे विश्वास है) मानक स्विच एक पूर्ण IL कोड में पूर्ण रूप में संकलित हो जाता है यदि, और यदि, और ब्लॉक होगा: जो मुझे लगता है कि एक बेहतर सिंटैक्स है वैसे भी। आप सभी मामले के बयानों को स्वत: पूर्ण करने के लिए पुनर्जीवन / वी.एस. की ढीली क्षमता करते हैं, लेकिन मुझे लगता है कि यह दुनिया का अंत नहीं है। यह व्यक्तिगत प्राथमिकता है लेकिन मैं स्विच स्टेटमेंट का प्रशंसक नहीं हूं।
मेमेडेवेलर

165

आप वर्गों के साथ जो चाहें प्राप्त कर सकते हैं:

public class Base
{
    public const int A = 1;
    public const int B = 2;
    public const int C = 3;
}
public class Consume : Base
{
    public const int D = 4;
    public const int E = 5;
}

अब आप इन वर्गों के समान उपयोग कर सकते हैं जब वे एनम थे:

int i = Consume.B;

अद्यतन (आपके प्रश्न के अपडेट के बाद):

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

public enum SomeEnum // this is the existing enum (from WSDL)
{
    A = 1,
    B = 2,
    ...
}
public class Base
{
    public const int A = (int)SomeEnum.A;
    //...
}
public class Consume : Base
{
    public const int D = 4;
    public const int E = 5;
}

// where you have to use the enum, use a cast:
SomeEnum e = (SomeEnum)Consume.B;

8
फिर आप इस वर्ग के खेतों को कैसे समझेंगे? मेरे लिए यह एक महत्वपूर्ण व्यवहार है:Enum.GetValues(typeof(MyEnum)
माइक डी क्लार्क

1
आप प्रतिबिंब का उपयोग कर सकते हैं: void Test() { foreach (System.Reflection.PropertyInfo pi in typeof(Consume).GetProperties()) { Console.WriteLine(pi.Name); } }
mnieto

2
आपको यह सुनिश्चित करने की आवश्यकता होगी कि प्रतिबिंब के साथ गुणों का जमाव विरासत में मिली वस्तु गुणों को अनदेखा कर दे।
रॉबर्ट

परावर्तन उस कार्य के लिए सुपर बदसूरत है।
dylanh724

1
परावर्तन का उपयोग करने की आवश्यकता नहीं है, codeproject.com/Articles/20805/Enhancing-C-Enums पर कार्यान्वयन इसे करने का एक अच्छा तरीका है, जैसा कि ऑब्जेक्ट बनाए जा रहे हैं, उन्हें एक सूची में जोड़ा जाता है और इस सूची का उपयोग किया जा सकता है वस्तु प्रकारों की सूची लौटाएं। जब आप इसे विरासत के साथ मिलाते हैं, तो आपको यह सुनिश्चित करना होगा कि आप विरासत वाली कक्षाओं के लिए सही सूची का उपयोग कर रहे हैं।
पीबीओ

112

संक्षिप्त जवाब नहीं है। यदि आप चाहें तो आप थोड़ा खेल सकते हैं:

आप हमेशा कुछ ऐसा कर सकते हैं:

private enum Base
{
    A,
    B,
    C
}

private enum Consume
{
    A = Base.A,
    B = Base.B,
    C = Base.C,
    D,
    E
}

लेकिन, यह सब बहुत अच्छा नहीं है क्योंकि Base.A! = Consume.A

आप हमेशा ऐसा कुछ कर सकते हैं, हालांकि:

public static class Extensions
{
    public static T As<T>(this Consume c) where T : struct
    {
        return (T)System.Enum.Parse(typeof(T), c.ToString(), false);
    }
}

आधार और उपभोग के बीच पार करने के लिए ...

आप इन्यूम्स के मूल्यों को किलों के रूप में भी डाल सकते हैं, और उन्हें एनम के बजाय इनट्स के रूप में तुलना कर सकते हैं, लेकिन इस तरह के बेकार भी।

विस्तार विधि वापसी को टाइप टी टाइप करना चाहिए।


4
मैं इसे खोदता हूं, यार। इस अवधारणा का उपयोग अपने ORM से मेरे सार्वजनिक इंटरफ़ेस (ORM संदर्भ के बिना उन) के लिए कुछ एनमों को बबल करने के लिए किया।
ऑब्जेक्टिव टाइप

5
काम की तुलना के लिए किसी को भी ईनाम दिया जा सकता है:Base.A == (Base)Consume.A
Kresimir

1
उपयोग (दशमलव) Base.A == (दशमलव) Consume.A। कारण: यह है कि कैसे थोड़ा झंडा / मुखौटा संयोजन कार्य करता है (उदाहरण के लिए Enum.IsDefined msdn.microsoft.com/en-us/library/… )। तो एनम को एक पूर्णांक में सेट किया जा सकता है जो एनम में परिभाषित नहीं है। परीक्षण का उपभोग करें = 123456;
TamusJRoyce

3
@TamusJRoyce दशमलव? intबहुत अधिक समझ में आता है। जब एक Enum में एक आंशिक हिस्सा होगा!?!?!
एरिक

कम से कम, यह सुनिश्चित करता है कि संबंधित एनम स्थिरांक का पूर्णांक मान समान है। आखिरकार, एनम केवल पूर्णांक स्थिरांक का एक सेट है। C # लागू नहीं करता है कि निर्दिष्ट मान vaild enum स्थिरांक हैं, अर्थात enums सख्त अर्थों में सुरक्षित नहीं हैं।
ओलिवियर जैकोट-डेसकॉम्ब्स

98

इंट कॉन्स्टेंट के साथ कक्षाओं का उपयोग करने से ऊपर के समाधान में टाइप-सेफ्टी का अभाव है। यानी आप नए मूल्यों का आविष्कार कर सकते हैं जो वास्तव में कक्षा में परिभाषित नहीं हैं। इसके अलावा उदाहरण के लिए इनपुट के रूप में इन वर्गों में से एक लेने वाली विधि लिखना संभव नहीं है।

आपको लिखना होगा

public void DoSomethingMeaningFull(int consumeValue) ...

हालांकि, जावा के पुराने दिनों का एक वर्ग आधारित समाधान है, जब कोई एनम उपलब्ध नहीं थे। यह लगभग enum- जैसा व्यवहार प्रदान करता है। एकमात्र चेतावनी यह है कि इन स्थिरांक का उपयोग स्विच-स्टेटमेंट के भीतर नहीं किया जा सकता है।

public class MyBaseEnum
{
    public static readonly MyBaseEnum A = new MyBaseEnum( 1 );
    public static readonly MyBaseEnum B = new MyBaseEnum( 2 );
    public static readonly MyBaseEnum C = new MyBaseEnum( 3 );

    public int InternalValue { get; protected set; }

    protected MyBaseEnum( int internalValue )
    {
        this.InternalValue = internalValue;
    }
}

public class MyEnum : MyBaseEnum
{
    public static readonly MyEnum D = new MyEnum( 4 );
    public static readonly MyEnum E = new MyEnum( 5 );

    protected MyEnum( int internalValue ) : base( internalValue )
    {
        // Nothing
    }
}

[TestMethod]
public void EnumTest()
{
    this.DoSomethingMeaningful( MyEnum.A );
}

private void DoSomethingMeaningful( MyBaseEnum enumValue )
{
    // ...
    if( enumValue == MyEnum.A ) { /* ... */ }
    else if (enumValue == MyEnum.B) { /* ... */ }
    // ...
}

7
मुझे लगता है कि यह सही उत्तर है। एनम के लिए आपके पास विरासत नहीं हो सकती है लेकिन यह आपको इसे प्रबंधित करने की अनुमति दे सकता है!
लोबोब

11
अच्छा और साफ। +1। बस एक संकेत, आपको वास्तव में सभी के लिए आवश्यक नहीं है।
इग्नासियो सोलर गार्सिया

1
मैंने कभी भी एन्युमरेशंस पर नहीं सोचा था जैसे कि आप FileOpenMode.Read> FileOpenMode.Write कह सकते हैं। अगर ऐसा है तो आपको उस एनम के लिए एक int या इससे भी बेहतर IEqualityComparer की जरूरत है। सादर।
इग्नासियो सोलर गार्सिया

3
यादृच्छिक के उपयोग से @binki objectअसेंबली की प्रत्येक तात्कालिकता के लिए मानों को अलग बनाती है ताकि उन्हें क्रमबद्ध नहीं किया जा सके।
ivan_pozdeev

2
लेकिन यह आपको MyEnum पर "स्विच" करने की अनुमति नहीं देता है, क्या यह करता है? मेरा मतलब है कि मुख्य रूप से मैं क्यों enums का उपयोग करता हूं ...
मेम्फिज़

13

इस तथ्य को अनदेखा करना कि आधार एक आरक्षित शब्द है जिसे आप एनम की विरासत के लिए नहीं कर सकते हैं।

सबसे अच्छी बात आप कुछ ऐसा कर सकते हैं:

public enum Baseenum
{
   x, y, z
}

public enum Consume
{
   x = Baseenum.x,
   y = Baseenum.y,
   z = Baseenum.z
}

public void Test()
{
   Baseenum a = Baseenum.x;
   Consume newA = (Consume) a;

   if ((Int32) a == (Int32) newA)
   {
   MessageBox.Show(newA.ToString());
   }
}

चूंकि वे सभी एक ही आधार प्रकार हैं (यानी: int) आप एक प्रकार के उदाहरण से दूसरे प्रकार के मूल्य को असाइन कर सकते हैं जो एक कास्ट है। आदर्श नहीं है लेकिन यह काम करता है।


2
आधार आरक्षित है लेकिन आधार नहीं है
erikkallen

2
वह ओप के आधार का उपयोग एनम नाम के रूप में करने की बात कर रहा है, यह सिर्फ एक उदाहरण का नाम है जो मुझे यकीन है
जॉन रसच

Genisio के जवाब के रूप में भी।
नवफाल

6

मुझे पता है कि यह उत्तर देर से आता है लेकिन मैंने यही किया है:

public class BaseAnimal : IEquatable<BaseAnimal>
{
    public string Name { private set; get; }
    public int Value { private set; get; }

    public BaseAnimal(int value, String name)
    {
        this.Name = name;
        this.Value = value;
    }

    public override String ToString()
    {
        return Name;
    }

    public bool Equals(BaseAnimal other)
    {
        return other.Name == this.Name && other.Value == this.Value;
    }
}

public class AnimalType : BaseAnimal
{
    public static readonly BaseAnimal Invertebrate = new BaseAnimal(1, "Invertebrate");

    public static readonly BaseAnimal Amphibians = new BaseAnimal(2, "Amphibians");

    // etc        
}

public class DogType : AnimalType
{
    public static readonly BaseAnimal Golden_Retriever = new BaseAnimal(3, "Golden_Retriever");

    public static readonly BaseAnimal Great_Dane = new BaseAnimal(4, "Great_Dane");

    // etc        
}

तब मैं ऐसा करने में सक्षम हूं:

public void SomeMethod()
{
    var a = AnimalType.Amphibians;
    var b = AnimalType.Amphibians;

    if (a == b)
    {
        // should be equal
    }

    // call method as
    Foo(a);

    // using ifs
    if (a == AnimalType.Amphibians)
    {
    }
    else if (a == AnimalType.Invertebrate)
    {
    }
    else if (a == DogType.Golden_Retriever)
    {
    }
    // etc          
}

public void Foo(BaseAnimal typeOfAnimal)
{
}

2
मैजिक नंबरों को स्टैकओवरफ्लो . com/questions/757684/… के अनुसार ऑब्जेक्ट से बदला जा सकता है । लेकिन इस विशेष मामले के लिए, आप विशिष्टता की गारंटी के लिए मौजूदा जैविक नामकरण की सुविधाओं का उपयोग करके दोनों दुनिया के सर्वश्रेष्ठ प्राप्त कर सकते हैं।
ivan_pozdeev

4

यह जो मैंने किया है। मैंने जो कुछ अलग किया है newवह "उपभोग" पर समान नाम और कीवर्ड का उपयोग करता है enum। चूंकि नाम का नाम enumसमान है, आप बस इसे बिना दिमाग के उपयोग कर सकते हैं और यह सही होगा। साथ ही आपको इंटेलीजेंस मिलता है। आपको बस यह ध्यान रखना होगा कि इसे सेट करते समय मानों को आधार से कॉपी किया जाए और उन्हें सिंक किया जाए। आप कोड टिप्पणियों के साथ मदद कर सकते हैं। यह एक और कारण है कि डेटाबेस में जब enumमूल्य संचय करते हैं तो मैं हमेशा स्ट्रिंग को संग्रहीत करता हूं, मान नहीं। क्योंकि अगर आप स्वचालित रूप से बढ़ते पूर्णांक मानों का उपयोग कर रहे हैं जो समय के साथ बदल सकते हैं।

// Base Class for balls 
public class BaseBall
{
    // keep synced with subclasses!
    public enum Sizes
    {
        Small,
        Medium,
        Large
    }
}

public class VolleyBall : BaseBall
{
    // keep synced with base class!
    public new enum Sizes
    {
        Small = BaseBall.Sizes.Small,
        Medium = BaseBall.Sizes.Medium,
        Large = BaseBall.Sizes.Large,
        SmallMedium,
        MediumLarge,
        Ginormous
    }
}

2
व्युत्पन्न वर्ग (जैसे SmallMedium = 100,) में नए मूल्यों के लिए एक अलग सीमा निर्धारित करने पर विचार करें , ताकि आप अपने सॉफ्टवेयर के पुराने संस्करणों के साथ संगतता रख सकें जब आप आधार वर्ग में नए मान जोड़ते हैं। उदाहरण के लिए, Hugeअपने बेस एनम में एक आकार जोड़ने 4से इसके मूल्य को निर्दिष्ट किया जाएगा , लेकिन 4पहले से ही SmallMediumव्युत्पन्न वर्ग द्वारा लिया जाता है।
रॉबर्टो

1
@ रॉबर्टो, इसे संबोधित करने के लिए, मैं कभी भी एनम वैल्यूज़ को बरकरार नहीं रखता, लेकिन केवल नाम। और उन्हें समकालिक रखना यहाँ एक आवश्यकता है। इसलिए Hugeआधार वर्ग में जोड़ने से Hugeपहले उपवर्ग में एक की आवश्यकता होगीSmallMedium
toddmo

2
BaseBallयहां होशियार नाम नहीं हो सकता है। यह उलझनभरा है। चूंकि एक बेसबॉल वास्तव में एक चीज है। यदि आपको याद है कि यह गेंद के लिए सिर्फ एक आधार वर्ग है, तो यह बहुत अजीब लगता है कि एक वॉलीबॉल शारीरिक रूप से छोटे बेसबॉल से विरासत में मिला है :)। मेरा सुझाव सिर्फ उपयोग करने के लिए हैBall
निक एन।

3

दूसरा तरीका

मेरी कंपनी में, हम गैर-सामान्य निचले स्तर की परियोजनाओं को प्राप्त करने के लिए "परियोजनाओं पर कूद" से बचते हैं। उदाहरण के लिए, हमारी प्रस्तुति / एपीआई परत केवल हमारे डोमेन परत को संदर्भित कर सकती है, और डोमेन परत केवल डेटा परत को संदर्भित कर सकती है।

हालाँकि, यह एक समस्या है, जब ऐसे एनम हैं जिन्हें प्रस्तुतिकरण और डोमेन लेयर्स दोनों द्वारा संदर्भित किए जाने की आवश्यकता है।

यहां समाधान है जिसे हमने (अब तक) लागू किया है। यह एक बहुत अच्छा समाधान है और हमारे लिए अच्छा काम करता है। अन्य उत्तर चारों ओर से घेर रहे थे।

मूल आधार यह है कि एनमों को विरासत में नहीं दिया जा सकता है - लेकिन कक्षाएं कर सकते हैं। इसलिए...

// In the lower level project (or DLL)...
public abstract class BaseEnums
{
    public enum ImportanceType
    {
        None = 0,
        Success = 1,
        Warning = 2,
        Information = 3,
        Exclamation = 4
    }

    [Flags]
    public enum StatusType : Int32
    {
        None = 0,
        Pending = 1,
        Approved = 2,
        Canceled = 4,
        Accepted = (8 | Approved),
        Rejected = 16,
        Shipped = (32 | Accepted),
        Reconciled = (64 | Shipped)
    }

    public enum Conveyance
    {
        None = 0,
        Feet = 1,
        Automobile = 2,
        Bicycle = 3,
        Motorcycle = 4,
        TukTuk = 5,
        Horse = 6,
        Yak = 7,
        Segue = 8
    }

फिर, एक और उच्च स्तरीय परियोजना में एनमों को "विरासत" देने के लिए ...

// Class in another project
public sealed class SubEnums: BaseEnums
{
   private SubEnums()
   {}
}

इसके तीन असली फायदे हैं ...

  1. एनम की परिभाषाएँ स्वचालित रूप से दोनों परियोजनाओं में समान हैं - परिभाषा के अनुसार।
  2. एनम परिभाषाओं में कोई भी बदलाव दूसरी कक्षा में कोई भी संशोधन किए बिना स्वचालित रूप से दूसरे में प्रतिध्वनित होता है।
  3. एनम एक ही कोड पर आधारित हैं - इसलिए मूल्यों की तुलना आसानी से की जा सकती है (कुछ कैविटीज़ के साथ)।

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

में दूसरी परियोजना जब फिर भी विरासत में मिला वर्ग के साथ काम कर, मैं नहीं मिल सका "स्थिर का उपयोग कर ..." काम करने के लिए दृष्टिकोण है, तो "विरासत में मिला enums" के सभी संदर्भ वर्ग के साथ उपसर्ग किया जाएगा, जैसे SubEnums.StatusType.Pending । अगर कोई दूसरी परियोजना में उपयोग किए जाने वाले "स्थिर" दृष्टिकोण का उपयोग करने की अनुमति देने के तरीके के साथ आता है , तो मुझे बताएं।

मुझे यकीन है कि इसे और भी बेहतर बनाने के लिए इसे ट्वीक किया जा सकता है - लेकिन यह वास्तव में काम करता है और मैंने काम करने वाली परियोजनाओं में इस दृष्टिकोण का उपयोग किया है।

अगर आपको यह मददगार लगे तो कृपया इसे अप-वोट करें।


2

मैं भी अधिभार Enums चाहते थे और का मिश्रण बनाया इस पृष्ठ पर 'सात' का जवाब और इस का डुप्लिकेट की पोस्ट पर Merlyn मॉर्गन-ग्राहम 'का जवाब है, साथ ही कुछ सुधार।
दूसरों पर मेरे समाधान के मुख्य लाभ:

  • अंतर्निहित int मान का स्वचालित वेतन वृद्धि
  • स्वचालित नामकरण

यह एक आउट-ऑफ-द-बॉक्स समाधान है और सीधे आपके प्रोजेक्ट में डाला जा सकता है। यह मेरी जरूरतों के लिए बनाया गया है, इसलिए यदि आपको इसके कुछ हिस्से पसंद नहीं हैं, तो बस इन्हें अपने कोड से बदल दें।

सबसे पहले, वहाँ आधार वर्ग है CEnumकि सभी कस्टम enums से वारिस होना चाहिए। यह .net Enumप्रकार के समान बुनियादी कार्यक्षमता है :

public class CEnum
{
  protected static readonly int msc_iUpdateNames  = int.MinValue;
  protected static int          ms_iAutoValue     = -1;
  protected static List<int>    ms_listiValue     = new List<int>();

  public int Value
  {
    get;
    protected set;
  }

  public string Name
  {
    get;
    protected set;
  }

  protected CEnum ()
  {
    CommonConstructor (-1);
  }

  protected CEnum (int i_iValue)
  {
    CommonConstructor (i_iValue);
  }

  public static string[] GetNames (IList<CEnum> i_listoValue)
  {
    if (i_listoValue == null)
      return null;
    string[] asName = new string[i_listoValue.Count];
    for (int ixCnt = 0; ixCnt < asName.Length; ixCnt++)
      asName[ixCnt] = i_listoValue[ixCnt]?.Name;
    return asName;
  }

  public static CEnum[] GetValues ()
  {
    return new CEnum[0];
  }

  protected virtual void CommonConstructor (int i_iValue)
  {
    if (i_iValue == msc_iUpdateNames)
    {
      UpdateNames (this.GetType ());
      return;
    }
    else if (i_iValue > ms_iAutoValue)
      ms_iAutoValue = i_iValue;
    else
      i_iValue = ++ms_iAutoValue;

    if (ms_listiValue.Contains (i_iValue))
      throw new ArgumentException ("duplicate value " + i_iValue.ToString ());
    Value = i_iValue;
    ms_listiValue.Add (i_iValue);
  }

  private static void UpdateNames (Type i_oType)
  {
    if (i_oType == null)
      return;
    FieldInfo[] aoFieldInfo = i_oType.GetFields (BindingFlags.Public | BindingFlags.Static);

    foreach (FieldInfo oFieldInfo in aoFieldInfo)
    {
      CEnum oEnumResult = oFieldInfo.GetValue (null) as CEnum;
      if (oEnumResult == null)
        continue;
      oEnumResult.Name = oFieldInfo.Name;
    }
  }
}

दूसरे, यहां 2 व्युत्पन्न एनुम वर्ग हैं। सभी व्युत्पन्न वर्गों को उम्मीद के मुताबिक काम करने के लिए कुछ बुनियादी तरीकों की आवश्यकता होती है। यह हमेशा एक ही बॉयलरप्लेट कोड होता है; मुझे बेस क्लास के लिए इसे आउटसोर्स करने का कोई तरीका अभी तक नहीं मिला है। वंशानुक्रम के पहले स्तर का कोड बाद के सभी स्तरों से थोड़ा भिन्न होता है।

public class CEnumResult : CEnum
{
  private   static List<CEnumResult>  ms_listoValue = new List<CEnumResult>();

  public    static readonly CEnumResult Nothing         = new CEnumResult (  0);
  public    static readonly CEnumResult SUCCESS         = new CEnumResult (  1);
  public    static readonly CEnumResult UserAbort       = new CEnumResult ( 11);
  public    static readonly CEnumResult InProgress      = new CEnumResult (101);
  public    static readonly CEnumResult Pausing         = new CEnumResult (201);
  private   static readonly CEnumResult Dummy           = new CEnumResult (msc_iUpdateNames);

  protected CEnumResult () : base ()
  {
  }

  protected CEnumResult (int i_iValue) : base (i_iValue)
  {
  }

  protected override void CommonConstructor (int i_iValue)
  {
    base.CommonConstructor (i_iValue);

    if (i_iValue == msc_iUpdateNames)
      return;
    if (this.GetType () == System.Reflection.MethodBase.GetCurrentMethod ().DeclaringType)
      ms_listoValue.Add (this);
  }

  public static new CEnumResult[] GetValues ()
  {
    List<CEnumResult> listoValue = new List<CEnumResult> ();
    listoValue.AddRange (ms_listoValue);
    return listoValue.ToArray ();
  }
}

public class CEnumResultClassCommon : CEnumResult
{
  private   static List<CEnumResultClassCommon> ms_listoValue = new List<CEnumResultClassCommon>();

  public    static readonly CEnumResult Error_InternalProgramming           = new CEnumResultClassCommon (1000);

  public    static readonly CEnumResult Error_Initialization                = new CEnumResultClassCommon ();
  public    static readonly CEnumResult Error_ObjectNotInitialized          = new CEnumResultClassCommon ();
  public    static readonly CEnumResult Error_DLLMissing                    = new CEnumResultClassCommon ();
  // ... many more
  private   static readonly CEnumResult Dummy                               = new CEnumResultClassCommon (msc_iUpdateNames);

  protected CEnumResultClassCommon () : base ()
  {
  }

  protected CEnumResultClassCommon (int i_iValue) : base (i_iValue)
  {
  }

  protected override void CommonConstructor (int i_iValue)
  {
    base.CommonConstructor (i_iValue);

    if (i_iValue == msc_iUpdateNames)
      return;
    if (this.GetType () == System.Reflection.MethodBase.GetCurrentMethod ().DeclaringType)
      ms_listoValue.Add (this);
  }

  public static new CEnumResult[] GetValues ()
  {
    List<CEnumResult> listoValue = new List<CEnumResult> (CEnumResult.GetValues ());
    listoValue.AddRange (ms_listoValue);
    return listoValue.ToArray ();
  }
}

कक्षाओं को सफलतापूर्वक कोडिंग कोड के साथ परीक्षण किया गया है:

private static void Main (string[] args)
{
  CEnumResult oEnumResult = CEnumResultClassCommon.Error_Initialization;
  string sName = oEnumResult.Name;   // sName = "Error_Initialization"

  CEnum[] aoEnumResult = CEnumResultClassCommon.GetValues ();   // aoEnumResult = {testCEnumResult.Program.CEnumResult[9]}
  string[] asEnumNames = CEnum.GetNames (aoEnumResult);
  int ixValue = Array.IndexOf (aoEnumResult, oEnumResult);    // ixValue = 6
}

1

एनम वास्तविक वर्ग नहीं हैं, भले ही वे इसे पसंद करते हों। आंतरिक रूप से, उन्हें उनके अंतर्निहित प्रकार (डिफ़ॉल्ट Int32 द्वारा) की तरह ही व्यवहार किया जाता है। इसलिए, आप केवल एक एनम से दूसरे में एकल मानों की "नकल" करके और समानता के लिए उनकी तुलना करने के लिए उनके पूर्णांक संख्या में कास्टिंग कर सकते हैं।


1

एनमों को अन्य एनमों से नहीं निकाला जा सकता है, लेकिन केवल इंट, यूंट, शॉर्ट, यूथोर्ट, लॉन्ग, अलॉन्ग, बाइट और सिबेट से।

जैसे पास्कल ने कहा, आप किसी एनम वैल्यू को इनिशियलाइज़ करने के लिए अन्य एनम के मान या स्थिरांक का उपयोग कर सकते हैं, लेकिन यह इसके बारे में है।


8
यह ग # सिंटैक्स की वजह से एक मिथ्या नाम है, लेकिन एनम वास्तव में int, uint, आदि से विरासत में नहीं मिल सकता है ... हुड के तहत वे अभी भी System.Enum से विरासत में मिला है। यह सिर्फ इतना है कि एनुम का प्रतिनिधित्व करने वाला सदस्य int, uint, आदि के लिए टाइप किया जाता है ...
JaredPar

@JaredPar। जब एक एनम को एक यूंट से प्राप्त किया जाता है, तो इसका मतलब है कि यह मान सभी यूंट हैं, आदि डिफ़ॉल्ट रूप से एक एनम विरासत में मिला है। (सी # विनिर्देश पर एक नज़र डालें, एनम सम एनीम: यूंट {...} वास्तव में काम करता है।)
जीरो लैंडर

4
दरअसल नहीं। यह System.enum विरासत में मिला है। जैसा कि पहले और अधिक बार यहां पोस्ट किया गया था, जो आपको लगता है कि उत्तराधिकार में सिर्फ एक लैंगगेज डसंबिगिटी है।
टॉमटॉम

1

एक अन्य संभावित समाधान:

public enum @base
{
    x,
    y,
    z
}

public enum consume
{
    x = @base.x,
    y = @base.y,
    z = @base.z,

    a,b,c
}

// TODO: Add a unit-test to check that if @base and consume are aligned

HTH


1

यह संभव नहीं है (जैसा कि @JaredPar ने पहले ही उल्लेख किया है)। इसके आसपास काम करने के लिए तर्क देने की कोशिश करना एक बुरा व्यवहार है। यदि आपके पास एक base classहै enum, तो आपको enum-valuesवहां हर संभव सूची चाहिए , और कक्षा के कार्यान्वयन को उन मूल्यों के साथ काम करना चाहिए जो इसे जानते हैं।

उदाहरण के लिए, आपके पास एक आधार वर्ग है BaseCatalog, और इसमें एक enum ProductFormats( Digital, Physical) है। फिर आपके पास एक MusicCatalogया BookCatalogऐसा हो सकता है जिसमें उत्पाद Digitalऔर Physicalउत्पाद दोनों हो सकते हैं , लेकिन यदि वर्ग है ClothingCatalog, तो इसमें केवल Physicalउत्पाद शामिल होने चाहिए ।


1

मुझे एहसास है कि मुझे इस पार्टी में थोड़ी देर हो गई है, लेकिन यहाँ मेरे दो सेंट हैं।

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

प्रस्तुत है: ObjectEnum

आप यहाँ कोड और प्रलेखन की जाँच कर सकते हैं: https://github.com/dimi3tron/ObjectEnum

और यहाँ पैकेज: https://www.nuget.org/packages/ObjectEnum

या बस इसे स्थापित करें: Install-Package ObjectEnum

संक्षेप में, ObjectEnum<TEnum>किसी भी एनम के लिए एक आवरण के रूप में कार्य करता है। उपवर्गों में GetDefinedValues ​​() को ओवरराइड करके, कोई भी निर्दिष्ट कर सकता है कि इस विशिष्ट वर्ग के लिए कौन से मान मान्य हैं।

एक संचालक ओवरलोड को एक ObjectEnum<TEnum>उदाहरण व्यवहार करने के लिए जोड़ा गया है जैसे कि यह परिभाषित मूल्य प्रतिबंधों को ध्यान में रखते हुए अंतर्निहित एनम का एक उदाहरण था। इसका मतलब है कि आप उदाहरण को आसानी से इंट या एनम मान से तुलना कर सकते हैं, और इस तरह इसे स्विच केस या किसी अन्य सशर्त में उपयोग कर सकते हैं।

मैं उदाहरण और आगे की जानकारी के लिए ऊपर उल्लिखित गितुब रेपो का उल्लेख करना चाहूंगा।

मुझे उम्मीद है कि आपको यह काम का लगेगा। बेझिझक टिप्पणी करें या आगे के विचारों या टिप्पणियों के लिए गितुब पर एक मुद्दा खोलें।

यहाँ आप के साथ क्या कर सकते हैं के कुछ छोटे उदाहरण हैं ObjectEnum<TEnum>:

var sunday = new WorkDay(DayOfWeek.Sunday); //throws exception
var monday = new WorkDay(DayOfWeek.Monday); //works fine
var label = $"{monday} is day {(int)monday}." //produces: "Monday is day 1."
var mondayIsAlwaysMonday = monday == DayOfWeek.Monday; //true, sorry...

var friday = new WorkDay(DayOfWeek.Friday);

switch((DayOfWeek)friday){
    case DayOfWeek.Monday:
        //do something monday related
        break;
        /*...*/
    case DayOfWeek.Friday:
        //do something friday related
        break;
}

-8

आप Enum में विरासत का प्रदर्शन कर सकते हैं, हालांकि यह केवल निम्न प्रकारों तक सीमित है। इंट, यूंट, बाइट, सोबते, शॉर्ट, यूथोर्ट, लॉन्ग, अलॉन्ग

उदाहरण के लिए

public enum Car:int{
Toyota,
Benz,
}

2
मुझे लगता है कि ओपी सिर्फ एक आधार सांख्यिक प्रकार से दूसरे से एक enum के वारिस के लिए, पूछ रहा था (जो सभी enums सी # में करते हैं, अनुमान से या स्पष्ट।)
reirab
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.