मैं सी # एक्सटेंशन विधियों के साथ एक वर्ग का विस्तार कैसे करूं?


98

क्या विस्तार विधियों को कक्षा में लागू किया जा सकता है?

उदाहरण के लिए, एक समय () विधि को शामिल करने के लिए DateTime का विस्तार करें जिसे इस तरह लागू किया जा सकता है:

DateTime.Tomorrow();

मुझे पता है कि मैं उपयोग कर सकता हूं

static DateTime Tomorrow(this Datetime value) { //... }

या

public static MyClass {
  public static Tomorrow() { //... }
}

इसी तरह के परिणाम के लिए, लेकिन मैं DateTime का विस्तार कैसे कर सकता हूं ताकि मैं DateTime.Tomorrow को लागू कर सकूं?

जवाबों:


70

आप किसी मौजूदा प्रकार के तरीकों को नहीं जोड़ सकते हैं जब तक कि मौजूदा प्रकार को आंशिक के रूप में चिह्नित नहीं किया जाता है, आप केवल उन विधियों को जोड़ सकते हैं जो एक्सटेंशन विधियों के माध्यम से मौजूदा प्रकार के सदस्य प्रतीत होते हैं। चूंकि यह मामला है, इसलिए आप प्रकार में स्थिर विधियों को नहीं जोड़ सकते क्योंकि एक्सटेंशन विधियाँ उस प्रकार के उदाहरणों का उपयोग करती हैं।

इस तरह अपनी खुद की स्थैतिक सहायक विधि बनाने से कुछ भी नहीं है:

static class DateTimeHelper
{
    public static DateTime Tomorrow
    {
        get { return DateTime.Now.AddDays(1); }
    }
}

जिसका उपयोग आप इस तरह करेंगे:

DateTime tomorrow = DateTimeHelper.Tomorrow;

6
हुह लूट? जब तक इसे 6 महीने के भीतर लागू नहीं किया गया और कुमुद का जवाब वहीं है, यह वास्तव में अधूरा लगता है!
क्रगॉक्स

4
@ कवास यह अधूरा नहीं है, एंड्रयू दिखा रहा है कि यह कैसे एक स्थिर सहायक के साथ किया जाना है, न कि एक विस्तार विधि के साथ (क्योंकि कोई उदाहरण नहीं है)।
निक एन।

1
तुम सही हो, निक। मैं हालांकि विस्तार विधियों को पसंद करता हूं! ;)
क्रेगॉक्स

2
Extensionmethod.net/csharp/datetime के बारे में क्या है ? IMHO, कम से कम सीखने की अवस्था के लिए बेहतर नमूने पूर्ण स्रोत कोड और अच्छे पैटर्न के साथ वास्तविक अनुप्रयोग हैं
किकेनेट

3
इस कोड के साथ समस्या यह है कि यह केवल DateTime.Now पर काम करता है न कि किसी DateTime ऑब्जेक्ट पर। उपयोगिता के रूप में, कोई इसका उपयोग कुछ पिछले (या भविष्य) के दिन को निर्धारित करने के लिए कर सकता है। दिनांक समय का उल्लेख नहीं। अब जब भी आप इसे कॉल करते हैं, तो यह निर्धारित किया जाता है ...
मिंटग्राउथ

181

एक विस्तार विधि का उपयोग करें ।

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

namespace ExtensionMethods
{
    public static class MyExtensionMethods
    {
        public static DateTime Tomorrow(this DateTime date)
        {
            return date.AddDays(1);
        }    
    }
}

उपयोग:

DateTime.Now.Tomorrow();

या

AnyObjectOfTypeDateTime.Tomorrow();

2
Shuggy का जवाब भी इसी तरह हल करने के लिए कुछ प्रकाश डाला।
क्रेगॉक्स

8
'ExtensionMethods का उपयोग कर' मत भूलना इसके लिए अपने दस्तावेज़ के शीर्ष पर।
ल्यूक एल्डर्टन

मैं DateTime.Tomorrow () क्यों नहीं कर सकता?
लफोटोग जूल

हाय लॉफटॉग, इस एक्सटेंशन को ऑब्जेक्ट की जरूरत है, यहां डेटटाइम एक स्ट्रक्चर है न कि ऑब्जेक्ट।
कुमु

4
जैसा कि पिछली टिप्पणियों में उल्लेख किया गया था (यह मेरे लिए स्पष्ट रूप से पर्याप्त नहीं था), आप DateTime.Tomorrow()केवल एक वर्ग और एक वर्ग संरचना के INSTANCES पर काम करने वाले विस्तार विधियों के रूप में उपयोग नहीं कर पाएंगे । क्लास स्ट्रक पर एक स्थिर विधि का "विस्तार" करने के लिए, एंड्रयू के उत्तर या शुगी के उत्तर का पालन ​​करें ।
एलेक्स

18

एक्सटेंशन विधियाँ स्टैटिक मेथड बनाने के लिए सिन्सेटिक शुगर होती हैं जिसका पहला पैरामीटर टाइप T लुक का उदाहरण है जैसे कि वे T पर एक इंस्टेंस विधि हैं।

इस तरह का लाभ काफी हद तक खो जाता है जहां आप 'स्टैटिक एक्सटेंशन मेथड्स' बनाते हैं क्योंकि वे कोड के रीडर को एक एक्सटेंशन विधि से भी अधिक भ्रमित करने के लिए काम करेंगे (क्योंकि वे पूरी तरह से योग्य प्रतीत होते हैं लेकिन वास्तव में उस वर्ग में परिभाषित नहीं होते हैं) बिना किसी क्रमिक लाभ के (उदाहरण के लिए लिनक के भीतर एक धाराप्रवाह शैली में कॉल कॉल करने में सक्षम)।

चूँकि आपको विस्तार का उपयोग करके दायरे में लाना होगा, वैसे भी मैं यह तर्क दूंगा कि यह बनाना सरल और सुरक्षित है:

public static class DateTimeUtils
{
    public static DateTime Tomorrow { get { ... } }
}

और फिर अपने कोड में इसका उपयोग करें:

WriteLine("{0}", DateTimeUtils.Tomorrow)

11

एक उत्तर के लिए निकटतम मैं एक System.Typeवस्तु में एक विस्तार विधि जोड़कर कर सकता हूं । सुंदर नहीं है, लेकिन अभी भी दिलचस्प है।

public static class Foo
{
    public static void Bar()
    {
        var now = DateTime.Now;
        var tomorrow = typeof(DateTime).Tomorrow();
    }

    public static DateTime Tomorrow(this System.Type type)
    {
        if (type == typeof(DateTime)) {
            return DateTime.Now.AddDays(1);
        } else {
            throw new InvalidOperationException();
        }
    }
}

अन्यथा, IMO एंड्रयू और ShuggyCoUk एक बेहतर कार्यान्वयन है।


इस दृष्टिकोण के साथ समस्याएं हैं। "टाइपोफ़ (...)" टाइप करने के लिए सुविधाजनक नहीं है, और इंटैलिजेंस के साथ आपको हर प्रकार के एक्सटेंशन दिखाई देंगे। फिर भी, यह एक दिलचस्प दृष्टिकोण है जिसे मैंने +1 के बारे में नहीं सोचा था।
मेटा-नाइट

@ मेटा-नाइट ट्रू, इसीलिए व्यक्तिगत रूप से मैं दूसरे के उत्तर को पसंद करता हूं। मेरे जवाब में ओपी प्रश्न के सबसे निकटतम वाक्यविन्यास होगा, लेकिन यह इस समस्या को हल करने का सबसे अच्छा तरीका नहीं है।
एड्रियन गोडोंग

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

3

मैं कुमुद की तरह ही करता

namespace ExtensionMethods
{
    public static class MyExtensionMethods
    {
        public static DateTime Tomorrow(this DateTime date)
        {
           return date.AddDays(1);
        }    
    }
}

लेकिन इसे इस नए DateTime () की तरह कहें। कल ();

सोचें कि यह DateTime.Now.Tomorrow () से अधिक जब्त करता है;


1
और आपने कुमु के जवाब पर टिप्पणी के रूप में लिखने का मौका गंवा दिया! : पी
क्रैगॉक्स

3

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

पूरा उदाहरण यहां देखें http://www.dotnetreaders.com/articles/Extension_methods_in_C-sharp.net,Methods_in_C_-sharp/201

उदाहरण:

class Extension
    {
        static void Main(string[] args)
        {
            string s = "sudhakar";
            Console.WriteLine(s.GetWordCount());
            Console.ReadLine();
        }

    }
    public static class MyMathExtension
    {

        public static int GetWordCount(this System.String mystring)
        {
            return mystring.Length;
        }
    }

3

मैं कुछ इसी तरह की तलाश कर रहा था - कक्षाओं पर बाधाओं की एक सूची जो एक्सटेंशन मेथड प्रदान करती है। एक संक्षिप्त सूची खोजने के लिए कठिन लगता है इसलिए यहाँ जाता है:

  1. आपके पास कोई निजी या संरक्षित कुछ भी नहीं हो सकता है - फ़ील्ड, विधियाँ, आदि।

  2. यह एक स्थिर वर्ग होना चाहिए, जैसे कि public static class...

  3. केवल विधियाँ कक्षा में हो सकती हैं, और उन्हें सार्वजनिक रूप से स्थिर होना चाहिए।

  4. आपके पास पारंपरिक स्थिर विधियां नहीं हो सकती हैं - जो इस तर्क को शामिल नहीं करती हैं उन्हें अनुमति नहीं है।

  5. सभी विधियाँ शुरू होनी चाहिए:

    सार्वजनिक स्थैतिक रिटर्न टाइप विधि नाम (यह क्लासनेम _this, ...)

तो पहला तर्क हमेशा यह संदर्भ है।

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

वर्कअराउंड अपने एक्सटेंशन मेथड क्लास को सिर्फ एक रेगुलर क्लास के लिए एक फेस के रूप में उपयोग करना है, और आपके एक्सटेंशन क्लास के सभी स्टैटिक तरीकों को सिर्फ असली क्लास कहते हैं, शायद एक सिंगलटन का उपयोग करना


2

दुर्भाग्य से, आप ऐसा नहीं कर सकते। मेरा मानना ​​है कि यह उपयोगी होगा, हालांकि। यह टाइप करना अधिक स्वाभाविक है:

DateTime.Tomorrow

से:

DateTimeUtil.Tomorrow

यूटिल क्लास के साथ, आपको एक के बजाय दो अलग-अलग वर्गों में एक स्थिर विधि के अस्तित्व की जांच करनी होगी।


1

हमने विवरण के साथ अपने उत्तर में सुधार किया है। अब विस्तार विधि के बारे में समझना अधिक आसान है

विस्तार विधि : यह एक ऐसा तंत्र है जिसके माध्यम से हम मूल वर्ग या संरचना को सब क्लासिंग या संशोधित या पुन: व्यवस्थित करने के बिना मौजूदा वर्ग के व्यवहार का विस्तार कर सकते हैं।

हम अपने कस्टम क्लासेस, .नेट फ्रेमवर्क क्लासेस आदि का विस्तार कर सकते हैं।

विस्तार विधि वास्तव में एक विशेष प्रकार की स्थैतिक विधि है जिसे स्थिर वर्ग में परिभाषित किया गया है।

जैसा कि DateTimeकक्षा पहले से ही ऊपर लिया गया है और इसलिए हमने स्पष्टीकरण के लिए इस वर्ग को नहीं लिया है।

नीचे उदाहरण है

// यह एक मौजूदा कैलकुलेटर वर्ग है जिसमें केवल एक ही विधि है (जोड़ें)

public class Calculator 
{
    public double Add(double num1, double num2)
    {
        return num1 + num2;
    }

}

// Below is the extension class which have one extension method.  
public static class Extension
{
    // It is extension method and it's first parameter is a calculator class.It's behavior is going to extend. 
    public static double Division(this Calculator cal, double num1,double num2){
       return num1 / num2;
    }   
}

// We have tested the extension method below.        
class Program
{
    static void Main(string[] args)
    {
        Calculator cal = new Calculator();
        double add=cal.Add(10, 10);
        // It is a extension method in Calculator class.
        double add=cal.Division(100, 10)

    }
}
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.