Enums में एक्सटेंशन विधियां कैसे जोड़ें


122

मेरे पास यह Enum कोड है:

enum Duration { Day, Week, Month };

क्या मैं इस Enum के लिए एक्सटेंशन विधियाँ जोड़ सकता हूँ?


1
आप यह देखा है? stackoverflow.com/questions/2422113/…
badpanda


संक्षिप्त उत्तर, हाँ। इस विशिष्ट मामले में आप उपयोग करना चाहते हैंTimeSpan
जोडरेल

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

2
मुझे ध्वज समूहों के लिए enum एक्सटेंशन विधियां पसंद हैं। मैं अगर उदाहरण के लिए खंड में पसंद करते हैं Day.IsWorkday()अधिक (Day & Days.Workday) > 0के साथ Days.Workdayके रूप में परिभाषित Monday | Tuesday ... | Friday। पूर्व मेरी राय में अधिक स्पष्ट है और वास्तव में बाद में लागू किया गया है।
सेबस्टियन वर्कर

जवाबों:


114

इस साइट के अनुसार :

विस्तार विधियाँ मौजूदा वर्गों के लिए तरीके लिखने का एक तरीका प्रदान करती हैं, जिस तरह से आपकी टीम के अन्य लोग वास्तव में खोज और उपयोग कर सकते हैं। यह देखते हुए कि एनम किसी भी अन्य की तरह कक्षाएं हैं, यह बहुत आश्चर्यचकित नहीं होना चाहिए कि आप उन्हें बढ़ा सकते हैं, जैसे:

enum Duration { Day, Week, Month };

static class DurationExtensions 
{
  public static DateTime From(this Duration duration, DateTime dateTime) 
  {
    switch (duration) 
    {
      case Day:   return dateTime.AddDays(1);
      case Week:  return dateTime.AddDays(7);
      case Month: return dateTime.AddMonths(1);
      default:    throw new ArgumentOutOfRangeException("duration");
    }
  }
}

मुझे लगता है कि enums सामान्य रूप से सबसे अच्छा विकल्प नहीं हैं, लेकिन कम से कम यह आपको कुछ स्विच को केंद्रीकृत करने देता है / यदि हैंडलिंग और उन्हें थोड़ा दूर करें, जब तक कि आप कुछ बेहतर नहीं कर सकते। मानों की जाँच करना याद रखें, रेंज में भी हैं।

आप यहां माइक्रोएसएफ एमएसडीएन पर अधिक पढ़ सकते हैं ।


मेरा मानना ​​है कि "दुश्मनी बुराई है" टिप्पणी जगह से बाहर है लेकिन वास्तविकता में एक आधार है। मुझे लगता है कि पता चलता है कि एक समस्या अति प्रयोग हो सकती है, क्योंकि वे आपको कुछ संदर्भों और व्यवहारों में लॉक करते हैं।
एड शीवम

1
एन # एन चूसना में एनम्स क्योंकि यह संकलित करता है और चलता है:Duration d = 0;
ग्राहम

16
Given that enums are classesनहीं, वे कक्षाएं नहीं हैं।
विंगर सेंडोन

1
मैं इस तरह के एक्सटेंशन का उपयोग केवल तभी करता हूं जब यह सीधे एनम के बारे में होता है, जैसे सप्ताह के दिनों और विस्तार के तरीके IsWeekday (), IsWeekendday ()। लेकिन कक्षाएं व्यवहार को एनकैप्सुलेट करने के लिए होती हैं, इसलिए यदि एनकैप्सुलेट करने के लिए बहुत सारे या जटिल व्यवहार हैं, तो एक वर्ग शायद बेहतर है। यदि यह सीमित और बुनियादी है, तो मैं व्यक्तिगत रूप से enums पर एक्सटेंशन ठीक करता हूं। अधिकांश डिज़ाइन निर्णयों के साथ-साथ विकल्पों (IMO) के बीच फ़ज़ी सीमाएँ होती हैं। यह ध्यान देने योग्य है कि एक्सटेंशन केवल शीर्ष स्तर के स्थिर वर्गों पर किए जा सकते हैं, नस्टेड क्लासेस नहीं। यदि आपका एनम एक वर्ग का हिस्सा है, तो आपको एक कक्षा बनाने की आवश्यकता होगी।
FreeText

51

आप Enum के उदाहरण के बजाय Enum प्रकार में एक एक्सटेंशन विधि जोड़ सकते हैं:

/// <summary> Enum Extension Methods </summary>
/// <typeparam name="T"> type of Enum </typeparam>
public class Enum<T> where T : struct, IConvertible
{
    public static int Count
    {
        get
        {
            if (!typeof(T).IsEnum)
                throw new ArgumentException("T must be an enumerated type");

            return Enum.GetNames(typeof(T)).Length;
        }
    }
}

आप ऊपर की विस्तार विधि कर सकते हैं:

var result = Enum<Duration>.Count;

यह एक सही विस्तार विधि नहीं है। यह केवल इसलिए काम करता है क्योंकि Enum <> System.Enum से भिन्न प्रकार का है।


क्या क्लास staticअपने सभी तरीकों को एक्सटेंशन की तरह सुनिश्चित करने के लिए हो सकता है?
जतिन सांघवी

15
भविष्य के पाठकों के लिए: नाम की अस्पष्टता Enum<T>थोड़ी भ्रमित करने वाली है। वर्ग को भी बुलाया जा सकता है EnumUtils<T>और विधि कॉल का समाधान होगा EnumUtils<Duration>.Count
नमोशेख

46

बेशक, आप उदाहरण के लिए कह सकते हैं, आप DescriptionAttribueअपने enumमूल्यों का उपयोग करना चाहते हैं:

using System.ComponentModel.DataAnnotations;

public enum Duration 
{ 
    [Description("Eight hours")]
    Day,

    [Description("Five days")]
    Week,

    [Description("Twenty-one days")] 
    Month 
}

अब आप कुछ ऐसा करने में सक्षम होना चाहते हैं:

Duration duration = Duration.Week;
var description = duration.GetDescription(); // will return "Five days"

आपकी एक्सटेंशन विधि GetDescription()निम्नानुसार लिखी जा सकती है:

using System.ComponentModel;
using System.Reflection;

public static string GetDescription(this Enum value)
{
    FieldInfo fieldInfo = value.GetType().GetField(value.ToString());
    if (fieldInfo == null) return null;
    var attribute = (DescriptionAttribute)fieldInfo.GetCustomAttribute(typeof(DescriptionAttribute));
    return attribute.Description;
}

मैं आपके द्वारा प्रदर्शन किए गए प्रदर्शन प्रदर्शन के अलावा, वास्तव में आपके द्वारा किए गए नमूने का विस्तार करने के लिए देख रहा था। चीयर्स
जॉर्ज

यह एक अच्छा विकल्प है, हालांकि मुझे लगता है कि नामस्थान सिर्फ System.ComponentModel है?
टॉमडेस्ट्री

अच्छा परिप्रेक्ष्य और कार्यान्वयन के साथ-साथ विस्तार कोड दिखाने के लिए धन्यवाद। पर ढेर करने के लिए: अपने कार्यान्वयन के साथ, आप इसे इस तरह भी कह सकते हैं: var description = Duration.Week.GetDescription ();
स्पेंसर सुलिवन

31

सभी उत्तर महान हैं, लेकिन वे एक विशिष्ट प्रकार के एनम में विस्तार विधि को जोड़ने के बारे में बात कर रहे हैं।

क्या होगा अगर आप सभी कास्टिंग के लिए एक विधि जोड़ना चाहते हैं जैसे कि स्पष्ट कास्टिंग के बजाय वर्तमान मूल्य का एक अंतर वापस करना?

public static class EnumExtensions
{
    public static int ToInt<T>(this T soure) where T : IConvertible//enum
    {
        if (!typeof(T).IsEnum)
            throw new ArgumentException("T must be an enumerated type");

        return (int) (IConvertible) soure;
    }

    //ShawnFeatherly funtion (above answer) but as extention method
    public static int Count<T>(this T soure) where T : IConvertible//enum
    {
        if (!typeof(T).IsEnum)
            throw new ArgumentException("T must be an enumerated type");

        return Enum.GetNames(typeof(T)).Length;
    }
}

इसके पीछे की चाल IConvertibleइसके वंशानुक्रम पदानुक्रम MDSN देखते हैं

उनके जवाब के लिए शॉनफर्ली को धन्यवाद


1
सबसे अच्छा जवाब!
मार्को अल्वेस

डिट्टो। यह काम करता है अगर मैं सीधे एक्सटेंशन (जैसे MyExtention.DoThing(myvalue)) को कॉल करता हूं, लेकिन वास्तव में myvalue.DoThing()
एनम

1
FYI करें, C # 7.3 अब Enum को एक सामान्य प्रकार की बाधा के रूप में समर्थन करता है
redetetrahedron

7

आप किसी भी चीज़ के लिए एक एक्सटेंशन बना सकते हैं, यहां तक ​​कि object(हालांकि यह सबसे अच्छा अभ्यास नहीं माना जाता है )। एक विस्तार विधि को एक public staticविधि के रूप में समझें । आप विधियों पर जो भी पैरामीटर-टाइप करते हैं, उसका उपयोग कर सकते हैं

public static class DurationExtensions
{
  public static int CalculateDistanceBetween(this Duration first, Duration last)
  {
    //Do something here
  }
}

5

MSDN देखें ।

public static class Extensions
{
  public static string SomeMethod(this Duration enumValue)
  {
    //Do something here
    return enumValue.ToString("D"); 
  }
}

7
एक voidएनम पर एक वापसी मूल्य अजीब तरह का है। मैं एक और अधिक यथार्थवादी नमूने के बारे में सोचूंगा।
Psubsee2003

3
@ psubsee2003 ओपी को निश्चित रूप से अपनी आवश्यकताओं के अनुरूप इसे बदलने के लिए पर्याप्त ज्ञान है? नमूना क्यों मायने रखता है, यह प्रारंभिक प्रश्न का उत्तर देने के लिए पर्याप्त है।
ल्यूकहेनरले

3
क्या मैं अकेला हूँ जो MSDN पर कोड उदाहरण अजीब पाता है? अधिकांश समय आपको यह समझने के लिए कुछ वास्तविक प्रयासों की आवश्यकता होती है कि वे क्या करने की कोशिश कर रहे हैं!
स्टैक्ड

0

हमने सिर्फ c # https://github.com/simonmau/enum_ext के लिए एनम एक्सटेंशन किया है

यह केवल एक प्रकार है, जो कि प्रकार के लिए लागू होता है, लेकिन यह बहुत अच्छा काम करता है इसलिए हमने इसे साझा करने के लिए एक पैकेज बनाया है - इसके साथ मज़े करें

public sealed class Weekday : TypeSafeNameEnum<Weekday, int>
{
    public static readonly Weekday Monday = new Weekday(1, "--Monday--");
    public static readonly Weekday Tuesday = new Weekday(2, "--Tuesday--");
    public static readonly Weekday Wednesday = new Weekday(3, "--Wednesday--");
    ....

    private Weekday(int id, string name) : base(id, name)
    {
    }

    public string AppendName(string input)
    {
        return $"{Name} {input}";
    }
}

मुझे पता है कि उदाहरण एक तरह से बेकार है, लेकिन आपको यह विचार मिलता है;)


0

एक साधारण वर्कअराउंड।

public static class EnumExtensions
{
    public static int ToInt(this Enum payLoad) {

        return ( int ) ( IConvertible ) payLoad;

    }
}

int num = YourEnum.AItem.ToInt();
Console.WriteLine("num : ", num);
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.