C# Iterator

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

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

BUY NOW DOWNLOAD READ ONLINE

C# Iterator: .NET Framework के पिछले Versions में यदि हम WatchArray की तरह कोई Custom Collection Create करना चाहते हैं, जो कि foreach Enumeration को Support करता हो, तो हमें IEnumerable IEnumerator Interface को Implement करने के अलावा कोई और तरीका उपलब्‍ध नहीं होता है। लेकिन .NET के नए Version में हमें ऐसे Types Create करने का एक और Alternative तरीका प्राप्त होता है, जो कि Iterators के माध्‍यम से foreach Loop को Support करता है।

Iterator एक Member Method, Accessor या Operator होता है जो Objects के एक Set में से विभिन्न Members को Start से Finish तक One by One Return करता है और इस बात को Specify करता है कि WatchArray जैसे किसी Container के Internal Items को foreach Statement का प्रयोग करते समय किस प्रकार से Return किया जाना चाहिए।

हालांकि Iterator Method का नाम भी GetEnumerator() ही होता है क्योंकि जब हम किसी Custom Collection को Iterators Concept के आधार पर Define करते हैं, तो .NET Platform Automatically उस Collection में Implement हो जाता है। यानी हमें हमारे Custom Collection Structure या Class में IEnumerable Interface को Manually Specify करने की जरूरत नहीं होती।

साथ ही Iterator Concept Use करते समय हमें GetEnumerator() Method के साथ ही एक IEnumerator Type का Valid Return Type भी Specify करना पडता जरूरी होता है। यदि हम इस नए तरीके को अपने पिछले Program में Implement करना चाहें, तो हमें हमारे WatchArray Type को निम्नानुसार तरीके से Modify करना होगा:

File Name: yieldKeywordUse.cs
using System;
using System.Collections;

namespace CSharpInterface
{
    public class Watch
    {
        internal byte hour, minute;
        internal string name;
    }

    class WatchArray : IEnumerable
    {
        Watch[] RoyalWatches = new Watch[4];

        public WatchArray()
        {
            RoyalWatches[0] = new Watch() { hour = 12, minute = 0, name = "HMT" };
            RoyalWatches[1] = new Watch() { hour = 10, minute = 10, name = "SONATA" };
            RoyalWatches[2] = new Watch() { hour = 5, minute = 40, name = "RADO" };
            RoyalWatches[3] = new Watch() { hour = 3, minute = 0, name = "TITAN" };
        }

        public IEnumerator GetEnumerator()
        {
            foreach (Watch x in RoyalWatches)
                yield return x;
        }
    }

    class UsingWatchArray
    {
        public static void Main(string[] args)
        {
            WatchArray Watches = new WatchArray();

            foreach (Watch x in Watches)
            {
                Console.WriteLine("Time of {0} - {1}:{2}", x.name, x.hour, x.minute);
            }
        }
    }
}

// Output:
   Time of HMT - 12:0
   Time of SONATA - 10:10
   Time of RADO - 5:40
   Time of TITAN - 3:0

इस Program में हमने केवल GetEnumerator() Method को निम्नानुसार तरीके से Modify किया है:

        public IEnumerator GetEnumerator()
        {
            foreach (Watch x in RoyalWatches)
                yield return x;
        }

जबकि शेष Code Exactly पिछले Program की तरह ही हैं। साथ ही ये Program Exactly पिछले Program की तरह ही Output दे रहा है, क्योंकि इस Program में हमने GetEnumerator() Method में yield Statement का प्रयोग किया है।

जैसाकि हम इस Code में देख सकते हैं कि GetEnumerator() Method के अन्दर ही हमने एक Internal foreach Logic Specify कर दिया है और इस Loop से ही हर Iteration में yield Statement का प्रयोग करते हुए Watch Type का एक Object Return कर दिया है।

yield Statement का प्रयोग Value या Set of Values को Caller Method के foreach Statement में Return करने का काम करता है। जब Program Control, yield Return Statement पर पहुंचता है, तो WatchArray Container की Current Location Temporarily Save हो जाती है और जब Iterator फिर से Call होता है, तो Next Time, Execution इसी Temporarily Saved Location से Restart होता है।

Loop in GetEnumerator() Method not Important

yield Statement को हमेंशा foreach Loop या किसी अन्‍य Looping Statement के साथ ही Use किया जाए, ऐसा जरूरी नहीं होता। बल्कि हम इसे Simple Statement के साथ भी Use कर सकते हैं।

उदाहरण के लिए यदि हम पिछले Code को बिना foreach Loop के Specify करें, तो हम इस Program के Codes को निम्नानुसार भी Specify कर सकते हैं:

            public IEnumerator GetEnumerator()
            {
                yield return RoyalWatches[0];
                yield return RoyalWatches[1];
                yield return RoyalWatches[2];
                yield return RoyalWatches[3];
            }

Collection के अन्दर GetEnumerator() Method को इस प्रकार से Define करने पर Main() Method में जब foreach Statement Use किया जाता है, तो ये Method हर बार इस Iterator में Enter करता है और yield Statement एक Value Return कर देता है।

Value Return करने के बाद जब फिर से Main() Method के foreach Loop का अगला Iteration होता है, तब GetEnumerator() Method में Specified अगला yield Statement Execute हो जाता है और ये प्रक्रिया तब तक चलती रहती है, जब तक कि Collection के सभी Elements Iterate नहीं हो जाते।

हालांकि यदि हम उपरोक्तानुसार तरीके से इस Method को Define करें और यदि हम RoyalWatches Array में एक और Object Add कर दें, तो वह Object RoyalWatches Array के Index Number 4 पर Store होगा। परिणामस्वरूप ये Method Compile Time Error Generate करेगा। इसलिए yield Method को हमेंशा GetEnumerator() Method में Specified foreach Loop द्वारा ही Use किया जाना चाहिए।

Stopping C# Iterator

कई बार हमें किसी Specific Situation में किसी Iterator के Iteration को रोकना होता है। इस जरूरत को पूरा करने के लिए हम उस Specific Situation में yield Contextual Keyword के साथ break Statement का प्रयोग कर सकते हैं। जैसे:

File Name: BreakingIterator.cs
using System;
using System.Collections;

namespace CSharpInterface
{
    public class Watch
    {
        internal byte hour, minute;
        internal string name;
    }

    class WatchArray : IEnumerable
    {
        Watch[] RoyalWatches = new Watch[4];

        public WatchArray()
        {
            RoyalWatches[0] = new Watch() { hour = 12, minute = 0, name = "HMT" };
            RoyalWatches[1] = new Watch() { hour = 10, minute = 10, name = "SONATA" };
            RoyalWatches[2] = new Watch() { hour = 5, minute = 40, name = "RADO" };
            RoyalWatches[3] = new Watch() { hour = 3, minute = 0, name = "TITAN" };
        }

        public IEnumerator GetEnumerator()
        {
            for (int i = 0; i < RoyalWatches.Length; i++)
            {
                if (i != 2)
                    yield return RoyalWatches[i];
                else
                    yield break;
            }
        }
    }

    class UsingWatchArray
    {
        public static void Main(string[] args)
        {
            WatchArray Watches = new WatchArray();

            foreach (Watch x in Watches)
            {
                Console.WriteLine("Time of {0} - {1}:{2}", x.name, x.hour, x.minute);
            }
        }
    }
}

Output:
	Time of HMT - 12:0
	Time of SONATA - 10:10

चूंकि इस Program में हमने हमारे GetEnumerator() Method को निम्नानुसार तरीके से Define किया है:

        public IEnumerator GetEnumerator()
        {
            for (int i = 0; i < RoyalWatches.Length; i++)
            {
                if (i != 2)
                    yield return RoyalWatches[i];
                else
                    yield break;
            }

जहां जैसे ही Variable i का मान 2 हो जाता है, if Statement False हो जाता है और Iterator Break हो जाता है। परिणामस्वरूप हमें Output में Collection के केवल दो ही Items प्राप्त होते हैं।

Named C# Iterator

yield Keyword का प्रयोग किसी भी Method में किया जा सकता है और जब हम किसी Method के अन्दर इसे Use करते हैं, तो इस प्रकार के Method को Named Iterator कहा जाता है। साथ ही Named Iterator Specify करते समय हमें हमेंशा इस बात का ध्‍यान रखना होता है कि Method हमेंशा IEnumerable Interface ही Return करे, IEnumerator Compatible Type नहीं।

यानी जब हम कोई ऐसा Method, Accessor या Operator Create करते हैं, जो कि एक IEnumerable Object का Reference Return करता है, तो ये Method इस Object को एक Iterator की तरह Supply करता है, जिसका General Form निम्नानुसार होता है:

	public IEnumerable itrName(ParameterList)
	{
		// Other codes… 
		yield return obj;
	}

इस Syntax में itrName हमारे Iterator Method का नाम है, जो कि ParameterList के रूप में 0 या अधिक Parameters Accept करता है और ये Pass होने वाले Parameters, Iterator Method को Pass होते हैं जबकि obj वह Object है, जो अगले Iteration में Current Iterator Method द्वारा Return होने वाला है।

जब एक बार हम Named Iterator Create कर देते हैं, तो उसके बाद हम इस Named Iterator को जहां कहीं भी Iterator की जरूरत होती है, वहां पर उपयोग में ले सकते हैं। उदाहरण के लिए हम foreach Loop को Control करने के लिए भी Named Iterator का प्रयोग कर सकते हैं।

Named Iterators कुछ परिस्थितियों में काफी उपयोगी होते हैं क्योंकि ये हमें हमारे Iterators को Arguments Pass करने की सुविधा Provide करते हैं, जिनके माध्‍यम से हम इस बात को Control कर सकते हैं कि Iterator, Collection के किन Items को Return करेगा।

उदाहरण के लिए हम Named Iterator Method को Collection के Beginning व Ending Point को Parameter के रूप में Pass करके Collection द्वारा Iterate होने वाले यानी Return होने वाले Items की Range निश्चित कर सकते हैं।

हमारे द्वारा Define किए गए Named Iterator को भी किसी भी अन्‍य Normal Method की तरह ही Overload किया जा सकता है। Named Iterator के Concept को समझने के लिए हम हमारे पिछले Program के WatchArray Class में GetWatch() नाम का एक Method निम्नानुसार तरीके से Define कर सकते हैं:

File Name: NamedIterator.cs
using System;
using System.Collections;

namespace CSharpInterface
{
    public class Watch
    {
        internal byte hour, minute;
        internal string name;
    }

    class WatchArray : IEnumerable
    {
        Watch[] RoyalWatches = new Watch[4];

        public WatchArray()
        {
            RoyalWatches[0] = new Watch() { hour = 12, minute = 0, name = "HMT" };
            RoyalWatches[1] = new Watch() { hour = 10, minute = 10, name = "SONATA" };
            RoyalWatches[2] = new Watch() { hour = 5, minute = 40, name = "RADO" };
            RoyalWatches[3] = new Watch() { hour = 3, minute = 0, name = "TITAN" };
        }

        public IEnumerator GetEnumerator()
        {
            foreach (Watch x in RoyalWatches)
                yield return x;
        }

        public IEnumerable GetWatch(bool returnReversed = false)
        {
            if (returnReversed)
            {
                for (int i = RoyalWatches.Length; i != 0; i--)
                    yield return RoyalWatches[i - 1];
            }
            else
            {
                foreach (Watch w in RoyalWatches)
                    yield return w;
            }
        }
    }

    class UsingWatchArray
    {
        public static void Main(string[] args)
        {
            WatchArray Watches = new WatchArray();

            //Get Watches using GetEnumerator() Method
            foreach (Watch x in Watches)
            {
                Console.WriteLine("Time of {0} - {1}:{2}", x.name, x.hour, x.minute);
            }
            Console.WriteLine();

            //Get Watches in Reverse using Named Iterator GetWatch() Method
            foreach (Watch x in Watches.GetWatch(true))
            {
                Console.WriteLine("Time of {0} - {1}:{2}", x.name, x.hour, x.minute);
            }

        }
    }
}

// Output:
   Time of HMT - 12:0
   Time of SONATA - 10:10
   Time of RADO - 5:40
   Time of TITAN - 3:0

   Time of TITAN - 3:0
   Time of RADO - 5:40
   Time of SONATA - 10:10
   Time of HMT - 12:0

इस तरह से इस Program द्वारा हम समझ सकते हैं कि yield Method को उपयुक्त तरीके से Use करके हम WatchArray जैसे किसी Custom Container से कई तरीकों से Results को Return करने के लिए Define कर सकते हैं, जिन्हें foreach Loop में Use किया जा सकता है।

इस प्रकार से यदि हम सारांश में समझें तो जब हम कोई Custom Container Type Define करते हैं और उसके सभी Data Elements को हम External Class में foreach Statement द्वारा Access करना चाहते हैं, तो हमें उस Container Class में GetEnumerator() Method को Implement करना जरूरी होता है, जो कि IEnumerable Interface Type में Declared है।

इसे Implement करने के लिए हम सामान्‍यत: Composition तरीके को Use करते हैं। यानी हम Container Class के अन्दर ही System.Array Type का Object Create करके Return कर सकते हैं या फिर हम Named Iterator Define कर सकते हैं, जैसाकि पिछले उदाहरण में किया है।

System.Array - Pre Implemented
LINQ Tutorial

******

ये पोस्‍ट Useful लगा हो, तो Like कर दीजिए।

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

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

BUY NOW DOWNLOAD READ ONLINE

Download All Hindi EBooks

सभी हिन्दी EBooks C, C++, Java, C#, ASP.NET, Oracle, Data Structure, VB6, PHP, HTML5, JavaScript, jQuery, WordPress, etc... के DOWNLOAD LINKS प्राप्‍त करें, अपने EMail पर।

Register करके Login करें। इस Popup से छुटकारा पाएें।