मान बदलने के लिए बिना Enum प्रकार का डिफ़ॉल्ट मान चुनना


208

सी # में, क्या यह संभव है कि एक एनुम प्रकार को एक विशेषता के साथ सजाया जाए या कुछ और निर्दिष्ट करने के लिए क्या डिफ़ॉल्ट मान होना चाहिए, बिना परिवर्तन के मान? आवश्यक संख्याओं को किसी भी कारण से पत्थर में सेट किया जा सकता है, और यह अभी भी डिफ़ॉल्ट पर नियंत्रण रखना आसान होगा।

enum Orientation
{
    None = -1,
    North = 0,
    East = 1,
    South = 2,
    West = 3
}

Orientation o; // Is 'North' by default.

क्या आपको int ?, double ?, आदि के लिए डिफ़ॉल्ट मान बदलने में सक्षम होना चाहिए?
AR

2
@AR नहीं आप पिछले करने के लिए अपराध है, लेकिन यह करने के लिए enums तुलना करने के लिए मतलब नहीं है intरों सार में , बस क्योंकि वे एक अंकीय प्रकार के रूप में लागू किया जाना होता है। हम स्ट्रिंग्स के रूप में एनम को लागू कर सकते हैं, और यह उनकी उपयोगिता को नहीं बदलेगा। मैं यहाँ उत्तर को C # भाषा की अभिव्यक्ति की सीमा मानता हूँ; सीमा निश्चित रूप से "एक प्रतिबंधित सेट से मूल्यों को अलग करने" के विचार में निहित नहीं है।
jpaugh

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

@AR प्वाइंट लिया। मुझे लगता है कि मैं बहुत अधिक समय enumटाइप-स्तर के निर्माणों के बारे में सोचता हूं , विशेष रूप से योग के प्रकार (या यहां देखें) । अर्थात, प्रत्येक एनम को एक अलग प्रकार के रूप में माना जाता है, जहां उस प्रकार के सभी मान हर दूसरे एनम के मूल्यों से अलग होते हैं। इस तरह की मानसिकता से, एनमों के लिए किसी भी मूल्य को साझा करना असंभव है , और वास्तव में, यह अमूर्तता अलग हो जाती है जब आप मानते हैं कि 0किसी दिए गए एनम के लिए डिफ़ॉल्ट मान्य नहीं हो सकता है, और बस हर एनुम में जूता-सींग वाला है।
jpaugh

हां, मैं भेदभाव वाली यूनियनों से परिचित हूं। C # Enums वह नहीं हैं, इसलिए मुझे नहीं पता कि यह इतने उच्च (और गलत) स्तर पर उनके बारे में सोचने में मददगार है। जबकि एक 'योग प्रकार' निश्चित रूप से इसके फायदे हैं, इसलिए करता है और enum (उचित मान प्रदान की जाती हैं)। जैसे myColor = Colors.Red | Colors.Blue। मेरा मुख्य बिंदु यह है कि यदि आप एक सी के लिए एक योग प्रकार चाहते हैं, तो एक को तैयार करें, बजाय एक एनम की अवधारणा को पुन: प्रस्तुत करने का प्रयास करने के लिए।
एआर

जवाबों:


349

एक enum(वास्तव में, किसी भी प्रकार के मूल्य) के लिए डिफ़ॉल्ट 0 है - भले ही उसके लिए कोई वैध मूल्य न हो enum। इसे बदला नहीं जा सकता।


13
यह पूछने के लिए प्रश्न पूछें कि एक इंट के लिए डिफ़ॉल्ट मान 42 है। सोचें कि कितना अजीब लगता है ... मेमोरी को रनटाइम द्वारा खाली कर दिया जाता है, इससे पहले कि आपको यह पता
चले

3
@DougS 1. नहीं, लेकिन आप गलत थे यह स्वीकार करते हैं। 2. उन्होंने टिप्पणी upvotes से कोई प्रतिष्ठा अर्जित नहीं की।
आस्के बी

7
टिप्पणियों से मुझे इस उत्तर के बारे में संदेह हुआ, इसलिए मैंने इसका परीक्षण किया और सत्यापित किया कि यह उत्तर निश्चित रूप से सही है।
इयान न्यूजन

1
@JamesCurran लेकिन जब एनमों I के लिए 0 मानों का उपयोग नहीं किया जाता है, तो "MyProjectName.dll में 'System.NullReferenceException' प्रकार का एक अपवाद उत्पन्न हुआ, लेकिन उपयोगकर्ता कोड में संभाला नहीं गया था। अतिरिक्त जानकारी: ऑब्जेक्ट संदर्भ किसी ऑब्जेक्ट के इंस्टेंस पर सेट किया गया है।" त्रुटि। इसे कैसे जोड़ेंगे? नोट: मैं एनम के विवरण को प्रदर्शित करने के लिए एक एक्सटेंशन विधि का उपयोग करता हूं, लेकिन यह सुनिश्चित नहीं करता कि इस पृष्ठ
जैक

64

किसी भी एनम का डिफ़ॉल्ट मान शून्य है। इसलिए यदि आप एक एन्यूमरेटर को डिफ़ॉल्ट मान सेट करना चाहते हैं, तो यह सेट करें कि एक शून्य और अन्य सभी एन्यूमरेटर्स को गैर-शून्य (पहला एनीमीटर को शून्य मानने वाला उस एनम के लिए डिफ़ॉल्ट मान होगा यदि कई एन्यूमरेटर हैं शून्य के साथ)।

enum Orientation
{
    None = 0, //default value since it has the value '0'
    North = 1,
    East = 2,
    South = 3,
    West = 4
}

Orientation o; // initialized to 'None'

यदि आपके प्रगणकों को स्पष्ट मानों की आवश्यकता नहीं है, तो सुनिश्चित करें कि पहला गणनाकर्ता वह है जिसे आप डिफ़ॉल्ट गणनाकर्ता बनना चाहते हैं, "डिफ़ॉल्ट रूप से, पहले गणना करने वाले का मान 0 है, और प्रत्येक क्रमिक गणक का मान बढ़ता है" 1. " ( C # संदर्भ )

enum Orientation
{
    None, //default value since it is the first enumerator
    North,
    East,
    South,
    West
}

Orientation o; // initialized to 'None'

38

यदि शून्य उचित डिफ़ॉल्ट मान के रूप में काम नहीं करता है, तो आप एनम के लिए वर्कअराउंड को परिभाषित करने के लिए घटक मॉडल का उपयोग कर सकते हैं:

[DefaultValue(None)]
public enum Orientation
{
     None = -1,
     North = 0,
     East = 1,
     South = 2,
     West = 3
 }

public static class Utilities
{
    public static TEnum GetDefaultValue<TEnum>() where TEnum : struct
    {
        Type t = typeof(TEnum);
        DefaultValueAttribute[] attributes = (DefaultValueAttribute[])t.GetCustomAttributes(typeof(DefaultValueAttribute), false);
        if (attributes != null &&
            attributes.Length > 0)
        {
            return (TEnum)attributes[0].Value;
        }
        else
        {
            return default(TEnum);
        }
    }
}

और फिर आप कॉल कर सकते हैं:

Orientation o = Utilities.GetDefaultValue<Orientation>();
System.Diagnostics.Debug.Print(o.ToString());

नोट: आपको फ़ाइल के शीर्ष पर निम्नलिखित पंक्ति को शामिल करना होगा:

using System.ComponentModel;

यह एनम के वास्तविक C # भाषा डिफ़ॉल्ट मान को परिवर्तित नहीं करता है, लेकिन वांछित डिफ़ॉल्ट मान को इंगित (और प्राप्त) करने का एक तरीका देता है।


क्षमा करें, यह आपके लिए काम नहीं करता है। क्या आप अधिक जानकारी जोड़ सकते हैं? आपको System.ComponentModel का उपयोग करके लाइन जोड़ने की आवश्यकता है; और फिर उपयोगिताएँ वर्ग में GetDefaultEnum () फ़ंक्शन लिखें। आप किस संस्करण का .net उपयोग कर रहे हैं?
डेविड

3
घटक मॉडल विशेषता और स्वच्छ समाधान के पुन: उपयोग के लिए +1। मैं सिफारिश करने के लिए आप में अंतिम पंक्ति को बदलना चाहते हैं elseके रूप में इस बयान: return default(TEnum);। मुट्ठी, यह धीमी को कम करेगाEnum.GetValues(...).*** कॉल , दूसरा (और अधिक महत्वपूर्ण) यह किसी भी प्रकार के लिए सामान्य होगा, यहां तक ​​कि गैर-एनम भी। इसके अलावा, आप केवल एनम के लिए उपयोग किए जाने वाले कोड को प्रतिबंधित नहीं करते हैं, इसलिए यह वास्तव में गैर-एनम प्रकारों पर उपयोग किए जाने पर संभावित अपवादों को ठीक करेगा।
Ivaylo Slavov

1
यह पूछे गए प्रश्न के संदर्भ में डिफ़ॉल्ट मूल्य विशेषता का दुरुपयोग हो सकता है। पूछा गया प्रश्न स्वचालित रूप से आरंभिक मूल्य के बारे में है, जो प्रस्तावित समाधान के साथ नहीं बदलेगा। यह विशेषता विज़ुअल डिज़ाइनर के डिफ़ॉल्ट के लिए प्रारंभिक मूल्य से भिन्न होती है। दृश्य डिजाइनर के सवाल पूछने वाले व्यक्ति द्वारा कोई उल्लेख नहीं किया गया है।
डेविड बर्ग

2
MSDN प्रलेखन में वास्तव में कुछ भी नहीं है कि ComponentModel या DefaultAttribute एक "विज़ुअल डिज़ाइनर" केवल सुविधा है। जैसा कि स्वीकृत उत्तर बताता है। संक्षिप्त उत्तर "नहीं, इसका असंभव" है 0 अंक के अलावा किसी अन्य के लिए किसी एनम के डिफ़ॉल्ट मान को फिर से परिभाषित करने के लिए। यह उत्तर एक वर्कअराउंड है।
डेविड

17

एक एनुम का डिफॉल्ट जो भी एन्यूमरेशन शून्य के बराबर है। मेरा मानना ​​है कि यह विशेषता या अन्य माध्यमों से परिवर्तनशील है।

(MSDN कहता है: "एक एनम ई का डिफ़ॉल्ट मान एक्सप्रेशन (ई) 0 द्वारा उत्पादित मूल्य है।")


13
कड़ाई से, इस मूल्य के साथ गणना करने की भी आवश्यकता नहीं है। शून्य अभी भी डिफ़ॉल्ट है।
मार्क Gravell

11

आप नहीं कर सकते हैं, लेकिन यदि आप चाहें, तो आप कुछ चाल कर सकते हैं। :)

    public struct Orientation
    {
        ...
        public static Orientation None = -1;
        public static Orientation North = 0;
        public static Orientation East = 1;
        public static Orientation South = 2;
        public static Orientation West = 3;
    }

सरल एनम के रूप में इस संरचना का उपयोग।
जहाँ आप pa == Orientation.East (या कोई भी मान जो आप चाहते हैं) बना सकते हैं, डिफ़ॉल्ट रूप
से चाल का उपयोग करने के लिए, आपको कोड से int से परिवर्तित करने की आवश्यकता है।
वहाँ कार्यान्वयन:

        #region ConvertingToEnum
        private int val;
        static Dictionary<int, string> dict = null;

        public Orientation(int val)
        {
            this.val = val;
        }

        public static implicit operator Orientation(int value)
        {
            return new Orientation(value - 1);
        }

        public static bool operator ==(Orientation a, Orientation b)
        {
            return a.val == b.val;
        }

        public static bool operator !=(Orientation a, Orientation b)
        {
            return a.val != b.val;
        }

        public override string ToString()
        {
            if (dict == null)
                InitializeDict();
            if (dict.ContainsKey(val))
                return dict[val];
            return val.ToString();
        }

        private void InitializeDict()
        {
            dict = new Dictionary<int, string>();
            foreach (var fields in GetType().GetFields(BindingFlags.Public | BindingFlags.Static))
            {
                dict.Add(((Orientation)fields.GetValue(null)).val, fields.Name);
            }
        } 
        #endregion

आपके निहित रूपांतरण ऑपरेटर में, आपको जरूरत है value + 1, अन्यथा अब आपके default(Orientation)रिटर्न East। इसके अलावा, कंस्ट्रक्टर को निजी बनाएं। अच्छी एप्रोच।
नवफाल

10

एक और तरीका जो सहायक हो सकता है - किसी प्रकार के "उपनाम" का उपयोग करने के लिए। उदाहरण के लिए:

public enum Status
{
    New = 10,
    Old = 20,
    Actual = 30,

    // Use Status.Default to specify default status in your code. 
    Default = New 
}

1
सुझाव अच्छा है, हालांकि, जैसा कि पहले से ही अन्य उत्तरों में उल्लेख किया गया है, गणना में उनके डिफ़ॉल्ट मान शून्य हैं। आपके मामले में, अभिव्यक्ति Status s = default(Status);किसी भी स्थिति के सदस्यों की sनहीं होगी , क्योंकि इसका मूल्य होगा (Staus) 0। उत्तरार्द्ध सीधे लिखने के लिए मान्य है, क्योंकि एनमर्स को पूर्णांक में डाला जा सकता है, लेकिन यह डीरियलाइज़ेशन के दौरान विफल हो जाएगा, क्योंकि फ्रेमवर्क यह सुनिश्चित करता है कि एक एनुम हमेशा मान्य सदस्य के लिए डिसेरलाइज़्ड है। यदि आप लाइन New = 10को बदलते हैं तो आपका कोड पूरी तरह से मान्य होगा New = 0
Ivaylo Slavov

1
हाँ। नया = 0 काम करेगा। मैं व्यक्तिगत रूप से स्पष्ट रूप से एनम सदस्यों की स्थापना नहीं करने से बचूंगा।
दिमित्री पावलोव

7

वास्तव में enum's डिफ़ॉल्ट' पहला तत्व है enumजिसका मूल्य है0

उदाहरण के लिए:

public enum Animals
{
    Cat,
    Dog,
    Pony = 0,
}
//its value will actually be Cat not Pony unless you assign a non zero value to Cat.
Animals animal;

9
हालाँकि, उस मामले में "टट्टू" IS "कैट" (जैसे, Console.WriteLine(Animals.Pony);"कैट" प्रिंट करता है)
जेम्स क्यूरन

16
वास्तव में आपको या तो होना चाहिए: किसी भी मूल्य को कभी भी निर्दिष्ट न करें या सभी मूल्यों को निर्दिष्ट न करें या केवल पहले परिभाषित सदस्य के मूल्य को निर्दिष्ट करें। यहां यह होता है कि: बिल्ली का कोई मूल्य नहीं है और यह 1 मूल्य है, इसलिए स्वचालित रूप से इसे 0 पर सेट किया जाता है। डॉग का कोई मूल्य नहीं है, स्वचालित रूप से इसे पिछलेवैल्यू + 1 पर सेट करता है। 1. पैसा का एक मूल्य है, मान छोड़ दें। तो कैट = पोनी = ०, डॉग = १. अगर आपके पास {कैट, डॉग, पोनी = ०, फ्रॉग} है तो डॉग = फ्रॉग = १
6२6६६४

4

The default value of enum is the enummember equal to 0 or the first element(if value is not specified) ... लेकिन मैंने अपनी परियोजनाओं में enum का उपयोग करके महत्वपूर्ण समस्याओं का सामना किया है और नीचे कुछ करके दूर किया है ... कभी मेरी आवश्यकता वर्ग स्तर से संबंधित कैसे थी ...

    class CDDtype
    {
        public int Id { get; set; }
        public DDType DDType { get; set; }

        public CDDtype()
        {
            DDType = DDType.None;
        }
    }    


    [DefaultValue(None)]
    public enum DDType
    {       
        None = -1,       
        ON = 0,       
        FC = 1,       
        NC = 2,       
        CC = 3
    }

और अपेक्षित परिणाम प्राप्त करें

    CDDtype d1= new CDDtype();
    CDDtype d2 = new CDDtype { Id = 50 };

    Console.Write(d1.DDType);//None
    Console.Write(d2.DDType);//None

अब क्या होगा यदि मान DB से आ रहा है .... इस परिदृश्य में ठीक है ... नीचे फ़ंक्शन में मान पास करें और यह मान को enum में बदल देगा ... नीचे फ़ंक्शन ने विभिन्न परिदृश्य को संभाला और यह सामान्य है ... और मुझे विश्वास है कि यह है बहुत तेज़ ..... :)

    public static T ToEnum<T>(this object value)
    {
        //Checking value is null or DBNull
        if (!value.IsNull())
        {
            return (T)Enum.Parse(typeof(T), value.ToStringX());
        }

        //Returanable object
        object ValueToReturn = null;

        //First checking whether any 'DefaultValueAttribute' is present or not
        var DefaultAtt = (from a in typeof(T).CustomAttributes
                          where a.AttributeType == typeof(DefaultValueAttribute)
                          select a).FirstOrNull();

        //If DefaultAttributeValue is present
        if ((!DefaultAtt.IsNull()) && (DefaultAtt.ConstructorArguments.Count == 1))
        {
            ValueToReturn = DefaultAtt.ConstructorArguments[0].Value;
        }

        //If still no value found
        if (ValueToReturn.IsNull())
        {
            //Trying to get the very first property of that enum
            Array Values = Enum.GetValues(typeof(T));

            //getting very first member of this enum
            if (Values.Length > 0)
            {
                ValueToReturn = Values.GetValue(0);
            }
        }

        //If any result found
        if (!ValueToReturn.IsNull())
        {
            return (T)Enum.Parse(typeof(T), ValueToReturn.ToStringX());
        }

        return default(T);
    }

-1 जानबूझकर दिए गए प्रश्न का उत्तर नहीं दे रहा है। यह एक स्पष्ट होमवर्क समस्या नहीं है, जो एकमात्र ऐसा मामला होना चाहिए जिसमें आप जानबूझकर जवाब नहीं देते हैं।
21

1
@Xynariz .. सॉरी दोस्तों .. मेरी टिप्पणी नकारात्मक रूप से गलत थी क्योंकि मेरा असली इरादा दूसरे तरीके से समाधान प्रदान करना था ... इसलिए मैंने अपनी टिप्पणियों को बदल दिया ...: D
Moumit

2

एक गणना प्रकार के लिए डिफ़ॉल्ट मान 0 है:

  • " डिफ़ॉल्ट रूप से, पहले एन्यूमरेटर का मान 0 होता है, और प्रत्येक क्रमिक एन्यूमरेटर का मान 1 से बढ़ जाता है। "

  • " वैल्यू टाइप एनम में एक्सप्रेशन (ई) 0, जहाँ ई एनम आइडेंटिफ़ायर होता है, का वैल्यू होता है। "

आप यहाँ C # enum के लिए दस्तावेज़ीकरण की जाँच कर सकते हैं , और C # डिफ़ॉल्ट मान तालिका के लिए दस्तावेज़ यहाँ देख सकते हैं


1

यदि आप डिफॉल्ट एनम को एनम के रूप में परिभाषित करते हैं, तो आप इसका उपयोग कर सकते हैं:

public enum MyEnum { His = -1, Hers = -2, Mine = -4, Theirs = -3 }

var firstEnum = ((MyEnum[])Enum.GetValues(typeof(MyEnum)))[0];

firstEnum == Mine.

यह नहीं मानती है कि एनम का शून्य मान है।


0

डिफ़ॉल्ट परिभाषा में पहला है। उदाहरण के लिए:

public enum MyEnum{His,Hers,Mine,Theirs}

Enum.GetValues(typeOf(MyEnum)).GetValue(0);

यह लौट आएगा His


haha; डिफ़ॉल्ट मान शून्य है। परंतु! वह कहते हैं, डिफ़ॉल्ट मान "शून्य" केवल पहले नामित मान का डिफ़ॉल्ट प्रतीक होता है; ! इसलिए दूसरे शब्दों में भाषा आपके बजाय डिफ़ॉल्ट का चयन करती है; यह भी बस इतना होता है कि शून्य एक int का डिफ़ॉल्ट मान है .. lol
user1953264

0
enum Orientations
{
    None, North, East, South, West
}
private Orientations? _orientation { get; set; }

public Orientations? Orientation
{
    get
    {
        return _orientation ?? Orientations.None;
    }
    set
    {
        _orientation = value;
    }
}

यदि आप संपत्ति को शून्य पर सेट करते हैं, तो आप ओरिएंटेशन वापस कर देंगे। प्रॉपर्टी _orientation डिफ़ॉल्ट रूप से शून्य है।


-5
[DefaultValue(None)]
public enum Orientation
{
    None = -1,
    North = 0,
    East = 1,
    South = 2,
    West = 3
}

फिर कोड में आप उपयोग कर सकते हैं

public Orientation GetDefaultOrientation()
{
   return default(Orientation);
} 

14
/ / \ WRONG /! \ DefaultValueAttribute वास्तव में मूल्य निर्धारित नहीं करता है, यह केवल सूचना प्रयोजनों के लिए है। फिर यह जांचना आपके ऊपर है कि क्या आपकी ईनम, फील्ड, प्रॉपर्टी, ... में वह विशेषता है। प्रॉपर्टीग्रिड इसका उपयोग करता है ताकि आप राइट क्लिक करें और "रीसेट" का चयन कर सकें, भले ही आप डिफ़ॉल्ट मान का उपयोग नहीं कर रहे हों, पाठ बोल्ड में दिखाया गया है - लेकिन - आपको अभी भी अपनी संपत्ति को डिफ़ॉल्ट रूप से इच्छित मूल्य पर सेट करना होगा।
user276648
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.