C# Delegate Example

Delegate is Callback

Modern Programming में जब कोई एक Method किसी दूसरे Method को Internally Invoke करता है, तो Internally Call होने वाले दूसरे Method को Callback Method या Callbacks कहा जाता है। इसलिए यदि हम उपरोक्त उदाहरण के आधार पर समझें तो callMethod() Internally, Display() Method को Invoke कर रहा है, इसलिए इस Program में Display() Method एक प्रकार का Callback Method है।

C# का Callback Methods को Support करने के लिए Design किए गए इस Delegate Concept से C# एक बहुत ही Powerful Programming Language बन जाती है, क्योंकि इस Delegate तरीके का प्रयोग करके हम विभिन्न प्रकार की जरूरतों को पूरा करने के लिए आसानी से ऐसे Program Develop कर सकते हैं, जिन्हें सामान्‍य तरीके से पूरा करना काफी Typical होता है।

उदाहरण के लिए कई बार Programming के दौरान हमारे सामने ऐसी स्थिति होती है कि किसी एक Method के Call हो जाने के बाद जो Value Return होती है, उस Value की जरूरत किसी दूसरे Method को होती है और जब तक उस दूसरे Method को वह Value Available न हो जाए, तब तक उस दूसरे Method को Invoke नहीं किया जा सकता। जबकि उस दूसरे Method को Value कब उपलब्‍ध होगी] ये बात हमारे Control में नहीं होती।

इस प्रकार की स्थिति में हमें उस दूसरे Method को एक Callback Method की तरह ही Use करना जरूरी होता है, क्योंकि इस दूसरे Method को पहला Method ही तब Invoke करता है, जब उसे वह Value प्राप्त हो जाती है, जिसकी जरूरत दूसरे Method को Invoke करने के लिए जरूरी है।

सामान्‍यत: Callback Methods के Concept की जरूरत तब होती है, जब हमारा कोई Method किसी Event के Trigger होने के बाद ही Execute हो सकता है। जैसे मानलो कि हम चाहते हैं कि जब तक Webpage Current Web Browser में पूरी तरह से Load न हो जाए, तब तक कोई Welcome Dialog Box Display न हो। लेकिन जैसे ही Webpage, Web Browser में पूरी तरह से Load हो, एक Welcome Dialog Box Display हो और Current User को Welcome Message दिखाई दे।

अब इस जरूरत में Webpage, Current Web Browser में कब Load होगा, ये बात पूरी तरह से Network की Speed, Internet Connection, Server की Speed, Webpage की Size आदि कई Factors पर Depend है, जिस पर हमारा एक Programmer के रूप में कोई Control नहीं हो सकता।

इसलिए इस स्थिति में Web Browser का load() नाम का JavaScript Method इस बात का ध्‍यान रखता है कि Current Webpage, Web Browser में पूरी तरह से कब Load हुआ और जब Webpage पूरी तरह से Load हो जाता है, तब यही load() Method JavaScript के alert() Method को Trigger करके Current User को Welcome करता है।

यानी alert() Method तब तक Execute नहीं होताए जब तक कि पूरा Webpage Load न हो जाए और पूरा Webpage कब Load होगा, इस बात पर हमारा कोई Control नहीं होता। इस स्थिति में हम Web Browser के load() JavaScript Method को ही ये जिम्मेदारी दे देते हैं, कि alert() Method को कब Call करना है।

इसलिए alert() Method वास्तव में एक Callback Method की तरह हो जाता है, जिसे load() Method के पूरी तरह से Execute हो जाने के बाद अथवा load() Method द्वारा Invoke किया जाता हैं, लेकिन कब Invoke किया जाएगा, ये बात पूरी तरह से हमारे Control से बाहर है।

Multicast – Multiple Callback Method Invocation

हालांकि हमने पिछले Delegate Reference में केवल एक ही Method को Initialize किया है, इसलिए जब हम callMethod को Invoke करते हैं, तो केवल Display() Method ही Execute होता है।

लेकिन कई बार हमें ऐसी जरूरत पडती है कि हमें Callback के रूप में बहुत सारे Methods को एक साथ Execute करना होता है। इस जरूरत को पूरा करने के लिए Delegate के साथ C# Compiler हमें Addition Operator का प्रयोग करने की सुविधा Provide करता है।

यानी Delegation Reference के साथ Addition Operator का प्रयोग करके हम एक ही Delegate Object में Same Signature and Return Type के एक से ज्यादा Methods को Assign कर सकते हैं और जब हम ऐसा करते हैं, तब एक ही Delegate Object की Invocation List में एक से ज्यादा Callable Methods Add हो जाते हैं। जैसे:

MyDelegate reference1 = new MyDelegate(obj.Display1);
MyDelegate reference2 = obj.Display2;
MyDelegate finalReference = reference1 + reference2;

इस Code Segment में finalReference के Invocation List में दो Methods हैं, जिन्हें finalReference नाम का Delegate Invoke कर सकता है। परिणामस्वरूप जब उस Delegate को Execute किया जाता है, तो उसकी Invocation List के सभी Methods Execute हो जाते हैं। इस प्रक्रिया को हम निम्न उदाहरण Program द्वारा बेहतर तरीके से समझ सकते हैं:

File Name: MultipleCallbackMethodInvocation.cs
using System;

namespace CSharpDelegate
{
    delegate void MyDelegate();	//Delegate Declaration

    class UsingDelegateWithMultipleCallbacks
    {
        static void Main()
        {
            MyDelegate callMethod = new MyDelegate(Display);
            callMethod += Hello;
            callMethod = callMethod + Hi;
            callMethod += Bye;

            callMethod();
        }

        public static void Display()
        {
            Console.WriteLine("This is Display() Method.");
        }

        public static void Hello()
        {
            Console.WriteLine("This is Hello() Method.");
        }

        public static void Hi()
        {
            Console.WriteLine("This is Hi() Method.");
        }

        public static void Bye()
        {
            Console.WriteLine("This is Bye Method.");
        }
    }
}

// Output:
	This is Display() Method.
	This is Hello() Method.
	This is Hi() Method.
	This is Bye Method.

इस Program में भी सबसे पहले हमने निम्नानुसार Statement द्वारा एक No-Argument No-Return Value Signature का MyDelegate नाम का Delegate Crete किया है:

delegate void MyDelegate();      //Delegate Declaration

और Main() Method में निम्नानुसार Statement द्वारा इस MyDelegate Type का एक callMethod नाम का Reference Variable Create करके उसे Display Parameter द्वारा Display() Method के Reference से Initialize किया है:

MyDelegate callMethod = new MyDelegate(Display);

हालांकि अभी तक callMethod में केवल Display() Method का ही Reference Stored है, इसलिए यदि हम अभी callMethod() Statement Specify करें, तो केवल Display() नाम का Static Method ही Call होगा।

लेकिन हमने इस callMethod नाम के Reference Variable के Object में +=+ Addition Operators को Use करके इसी Class में Defined Hello, HiBye नाम के Methods के References Assign कर दि, हैं। परिणामस्वरूप जब निम्नानुसार तीनों Statements Execute हो जाते हैं:

callMethod += Hello;
callMethod = callMethod + Hi;
callMethod += Bye;

तो callMethod reference Variable द्वारा Referenced Object में Display(), Hello(), Hi()Bye() नाम के चारों Static Methods का Reference Store हो जाता है। परिणामस्वरूप जब हम निम्नानुसार callMethod() Object के साथ Parenthesis को Specify करते हैं:

callMethod();

तो C# Compiler इस MyDelegate Type के Object को एक Method की तरह Execute करता है। परिणामस्वरूप इस Object में Data के रूप में Stored चारों ही Methods के Reference के माध्‍यम से Display(), Hello(), Hi() Bye() नाम के चारों ही Methods Invoke हो जाते हैं और हमें निम्नानुसार Output प्राप्त होता है:

This is Display() Method.
This is Hello() Method.
This is Hi() Method.
This is Bye Method.

जो इसी बात का Indication है कि चारों ही Methods callMethod() द्वारा Callback Methods की तरह Invoke हुए हैं।

Deleting Method from Invocation List – C# Delegate Example

जिस तरह से हम Delegate Type के Object के साथ Addition Operator का प्रयोग करके Delegate Object की Invocation List में Callable Methods को Add करते हैं, उसी तरह से हम Subtraction (or -=) Operators का प्रयोग करके Invocation List से किसी Method के Reference को Remove भी कर सकते हैं। जैसे:

File Name: DeleteCallbackFromMethodInvocationList.cs
using System;

namespace CSharpDelegate
{
    delegate void MyDelegate();	//Delegate Declaration

    class DeleteCallbackFromMethodInvocationList
    {
        static void Main()
        {
            MyDelegate callMethod = new MyDelegate(Display);
            Console.WriteLine("After adding all methods in Invocation List");
            callMethod += Hello;
            callMethod = callMethod + Hi;
            callMethod += Bye;

            callMethod();

            Console.WriteLine("\nAfter deleting Hi() and Bye() methods from Invocation List");
            callMethod -= Hi;
            callMethod = callMethod - Bye;

            callMethod();
        }

        public static void Display()
        {
            Console.WriteLine("This is Display() Method.");
        }

        public static void Hello()
        {
            Console.WriteLine("This is Hello() Method.");
        }

        public static void Hi()
        {
            Console.WriteLine("This is Hi() Method.");
        }

        public static void Bye()
        {
            Console.WriteLine("This is Bye Method.");
        }
    }
}

// Output:
   After adding all methods in Invocation List
   This is Display() Method.
   This is Hello() Method.
   This is Hi() Method.
   This is Bye Method.

   After deleting Hi() and Bye() methods from Invocation List
   This is Display() Method.
   This is Hello() Method.

ये Program पिछले Program की तरह ही सबसे पहले callMethod Reference Variable द्वारा Invocation List में निम्नानुसार Statements के माध्‍यम से चारों Method को Add करता है:

callMethod += Hello;
callMethod = callMethod + Hi;
callMethod += Bye;

परिणामस्वरूप जब हम पहली बार callMethod को निम्नानुसार Invoke करते हैं:

callMethod();

तो हमें निम्नानुसार Output प्राप्त होता है:

After adding all methods in Invocation List
This is Display() Method.
This is Hello() Method.
This is Hi() Method.
This is Bye Method.

जबकि जब निम्न Statements Execute होते हैं:

callMethod -= Hi;
callMethod = callMethod – Bye;

तो callMethod द्वारा Referenced MyDelegate Object की Invocation List से Hi() व Bye() Methods के Reference Delete हो जाते हैं। परिणामस्वरूप जब इस बार निम्नानुसार तरीके से callMethod द्वारा Invocation List के सभी Callback Methods को Invoke करते हैं:

callMethod();

तो हमें निम्नानुसार Output प्राप्त होता है:

After deleting Hi() and Bye() methods from Invocation List
This is Display() Method.
This is Hello() Method.

जहां हम देख सकते हैं कि इस बार Display() व Hello() नाम के केवल दो ही Methods Execute होते हैं। क्योंकि Hi() व Bye() नाम के दोनों Methods को हमने Subtract Operators का प्रयोग करके Invocation List से Delete कर दिया था।

Callbacks Invocation with Return Value

जिस तरह से हम किसी No-Argument No-Return Value Callback Method को Delegate के माध्‍यम से Invoke करते हैं, उसी तरह से हम किसी ऐसे Callback Method को भी Delegate के माध्‍यम से Invoke कर सकते हैं, जो कि कोई Parameter Accept करता हो अथवा Value Return करता हो।

लेकिन जब हम Delegate द्वारा ऐसे Callback Methods को Invoke करते हैं, जो कि कोई Value Return करते हों और Delegate के Invocation List में एक से ज्यादा Callback Methods हों, तो Delegate Object, Invocation List के केवल अन्तिम Callback Method की Value ही Return करता है, जबकि Invocation List के अन्‍य सभी Callback Methods की Return Value को Ignore कर देता है। Delegate के इस Behavior को हम निम्न Program द्वारा बेहतर तरीके से समझ सकते हैं:

File Name: CallbackWithReturnValue.cs
using System;

namespace CSharpDelegate
{
    delegate string MyDelegate(string name);

    class CallbackWithReturnValue
    {
        static void Main()
        {
            MyDelegate callMethod = new MyDelegate(Display);
            callMethod += Hello;
            callMethod = callMethod + Hi;
            callMethod += Bye;

            Console.WriteLine(callMethod("Kuldeep"));
        }

        public static string Display(string name)
        {
            return string.Format("Name: " + name);
        }

        public static string Hello(string name)
        {
            return string.Format("Hello! " + name);
        }

        public static string Hi(string name)
        {
            return string.Format("Hi! " + name);
        }

        public static string Bye(string name)
        {
            return string.Format("Bye " + name);
        }
    }
}

// Output:
	This is Bye Method.

जैसाकि इस Program के Output में हम देख सकते हैं कि Invocation List से केवल अन्तिम Callback Method यानी Bye() द्वारा Returned Message ही Display हो रहा है, क्योंकि हमारे Program में callMethod Delegate की Invocation List में Add किया गया अन्तिम Method Bye() ही है।

इस Program में हम Delegate के माध्‍यम से जिन Callback Methods को Invoke कर रहे हैं, वे Parameter भी Accept करते हैं और Value भी Return करते हैं। इसलिए इस Program में हमने callMethod Delegate Object को निम्नानुसार Specify किया है:

callMethod(“Kuldeep”)

जब हम Delegate Object को Parameter के साथ Invoke करते हैं, तो Delegate Object की Invocation List में जितने भी Callback Methods होते हैं, उन सभी को वह Parameter प्राप्त हो जाता है, जिसे हमने Delegate में Parameter की तरह Specify किया होता है।

इसलिए जब उपरोक्त Statement Execute होता है, तो callMethod Delegate की Invocation List में Specified Display(), Hello(), Hi() Bye() सभी Methods को Parameter के रूप में “Kuldeep” String प्राप्त होता है।

Callback Invocation with Reference Parameter

यदि किसी Delegate में Reference Parameter Specify किया जाता है, तो Parameter की Value को Invocation List द्वारा Invoke होने वाले किसी Callback Method से Return होने वाली Value से Change किया जा सकता है। परिणामस्वरूप जब Invocation List का अगला Method Invoke होता है, तो उस Invoked Method से Return होने वाली Value को Delegate Parameter के रूप में Use किया जा सकता है।

जिस तरह से हम किसी Normal Method में Parameters को ref Keyword के साथ By Reference Pass कर सकते हैं, उसी तरह से हम किसी Delegate में भी Parameter के रूप में ref Keyword युक्त Parameter Pass कर सकते हैं। जैसे:

File Name: CallbackWithRefParameter.cs
using System;

namespace CSharpDelegate
{
    delegate void MyDelegate(ref int value);

    class CallbackWithRefParameter
    {
        static void Main()
        {
            MyDelegate callMethod = new MyDelegate(Calculate1);
            callMethod += Calculate2;

            int xValue = 5;
            callMethod(ref xValue);
            Console.WriteLine("xValue: " + xValue);
        }

        public static void Calculate1(ref int val)
        {
            val = val * val;
        }

        public static void Calculate2(ref int val)
        {
            val += 100;
        }
    }
}

// Output:
	xValue = 125

इस Program में हमने निम्नानुसार एक Delegate Declare किया है, जो कि Integer Type के Reference के रूप में एक Parameter Accept करता है लेकिन कोई Value Return नहीं करता%

delegate void MyDelegate(ref int value);

फिर हमने निम्नानुसार Statements द्वारा Delegate Type का एक Object callMethod Create किया है और उसमें Calculate1()Calculate2() Methods के Reference को Data की तरह Store किया है:

MyDelegate callMethod = new MyDelegate(Calculate1);
callMethod += Calculate2;

फिर निम्नानुसार Statement द्वारा xValue नाम का एक Integer Type का Variable Declare किया है, जिसका मान 5 है और उसे callMethod Delegate में ref Keyword के साथ Pass किया है:

int xValue = 5;
callMethod(ref xValue);

परिणामस्वरूप callMethod सबसे पहले निम्नानुसार Calculate1() Method को Invoke करता है और उसमें xValue का Reference Parameter के रूप में Pass करता है:

        public static void Calculate1(ref int val)
        {
            val = val * val;
        }

चूंकि हमने xValue को ref Keyword के साथ Specify किया है, इसलिए इस Callback Method में जब Calculation Perform होता है, तो xValue Variable का Actual मान Change होकर 5 से 25 हो जाता है।

फिर जब callMethod Delegate Calculate2() Method को Invoke करता है, तो उसमें भी Parameter के रूप में xValue का मान ref Keyword के साथ Send करता है। परिणामस्वरूप Calculate2 Method में xValue का मान इस बार 5 नहीं बल्कि 25 Pass होता है, जो कि Calculate1() Callback Method द्वारा Returned Value है।

Calculate2() Method भी इस xValue के Actual मान 25 में 100 Add करता है और Final मान 125 फिर से xValue में Store हो जाता है। परिणामस्वरूप हमें Output के रूप में xValue का मान 125 दिखाई देता है।

इस तरह से हम समझ सकते हैं कि Callback Method में यदि किसी Parameter को ref Keyword के साथ Specify किया जाता है, तो हर अगले Callback Method को Parameter के रूप में Pass किए गए Variable का Actual व Modified Latest मान प्राप्त होता है और हर Callback Method उस Variable के Actual मान को Modify कर सकता है। जिसकी वजह से Variable का मान कई स्तर पर Change हो सकता है।

Instance Method and External Static Method as Callback

अभी तक हमने जितने भी Programs देखे हैं, उन सभी में हमने समान Class में Defined Static Method को ही Delegate द्वारा Invoke किया है। लेकिन यदि हम चाहें तो हम किसी Class के Instance Method को अथवा किसी External Class में Defined किसी Static Method को भी Callback की तरह Invoke कर सकते हैं।

पिछले सभी Programs में हमने केवल Static Method को ही Callback की तरह Delegate Object में Add किया है, जबकि सभी Static Methods Same Class में होने की वजह से उन्हें Delegate में Add करने के लिए हमने Directly उनके नाम को निम्नानुसार Specify किया है:

MyDelegate callMethod = new MyDelegate(Display);
callMethod += Hello;
callMethod = callMethod + Hi;
callMethod += Bye;

लेकिन जब हम किसी Class के Instance Method को Delegate के माध्‍यम से Callback की तरह Invoke करना चाहते हैं, तब हमें Object के नाम के साथ Dot Operator का प्रयोग करके Method को Specify करना होता है।

जबकि किसी External Class में Defined Static Method को Delegate के माध्‍यम से Callback की तरह Invoke करने के लिए हमें Class के नाम के साथ Dot Operator का प्रयोग करके Static Method को Specify करना होता है। इन दोनों तरीकों के बारे में हम निम्नानुसार Program द्वारा बेहतर तरीके से समझ सकते हैं:

File Name: InstanceMethodAndExternalStaticMethod.cs
using System;

namespace CSharpDelegate
{
    delegate void MyDelegate();

    public class UseDelegate
    {
        public void Display()
        {
           Console.WriteLine("I am Instance Method in UseDelegate Class being called via Delegate");
        }

        public static void Show()
        {
           Console.WriteLine("I am Static Method in UseDelegate Class being called via Delegate");
        }
    }

    class InstanceMethodAndExternalStaticMethod
    {
        static void Main()
        {
            MyDelegate callMethod = new MyDelegate(UseDelegate.Show);
            UseDelegate instance = new UseDelegate();
            callMethod += instance.Display;
            callMethod();
        }
    }
}

// Output:
   I am Static Method in UseDelegate Class being called via Delegate
   I am Instance Method in UseDelegate Class being called via Delegate

इस Program में हमने UseDelegate नाम की एक External Class Create की है और इस Class में Display() नाम का एक Normal Method Create किया है साथ ही Show() नाम का एक Static Method Create किया है।

फिर दूसरी Class में Defined Main() Method में हमने निम्नानुसार तरीके से UseDelegate Class के Static Method को callMethod नाम के Delegate Object में Initialize किया है:

MyDelegate callMethod = new MyDelegate(UseDelegate.Show);

जहां हम देख सकते हैं कि UseDelegate नाम की External Class में Defined Show() नाम के Static Method को Delegate के Invocation List में Add करने के लिए हमने Class के नाम के साथ Dot Operator का प्रयोग करते हुए Static Method के नाम को Specify किया है।

जबकि पिछले Programs में हम Static Method को केवल उनके नाम से ही Specify कर रहे थे। क्योंकि उन Programs में Static Method Same Class में था, जबकि इस Program का Static Method एक External Class में है।

चूंकि हम हमारे Delegate में एक Instance Method को भी Callback की तरह Add करना चाहते हैं। इसलिए हमने निम्नानुसार UseDelegate Type का instance नाम का एक Object Create किया है:

UseDelegate instance = new UseDelegate();

और इस instance Object के लिए Dot Operator का प्रयोग करके Display() Method को Specify करते हुए Delegate में निम्नानुसार Add किया है:

callMethod += instance.Display;

चूंकि इस Program में Display() Show() दोनों ही Methods का Signature व Return Type समान है, इसलिए हम इन दोनों ही Methods को Delegate Object callMethod के माध्‍यम से Invoke कर सकते हैं और जब हम callMethod Delegate द्वारा Referenced Invocation List के सभी Methods को निम्नानुसार Statement द्वारा Invoke करते हैं:

callMethod();

तो हमें उपरोक्त Program के अन्त में Specified Output प्राप्त होता है।

C# in Hindiये Article इस वेबसाईट पर Selling हेतु उपलब्‍ध EBook C#.NET in Hindi से लिया गया है। इसलिए यदि ये Article आपके लिए उपयोगी रहा, तो निश्चित रूप से ये पुस्तक भी आपके लिए काफी उपयोगी साबित होगी। 

C#.NET in Hindi | Page:908 | Format: PDF

BUY NOW GET DEMO REVIEWS