Anonymous Types in C#

Anonymous Types in C#

Anonymous Types in C#: C# हमें ऐसी सुविधा देता है कि हम जिस तरह से Unnamed Methods Create कर सकते हैं उसी तरह से हम Unnamed Types भी Create कर सकते हैं, जिसका कोई नाम नहीं होता। इन Anonymous Types को सामान्‍यत: LINQ Queries से Generate होने वाले Results के लिए Use किया जाता है। यानी इसका मुख्‍य उद्देश्‍य एक ऐसा Object Create करना होता है जो कि select Clause द्वारा Return हो।

सामान्‍यत: किसी Query से Return होने वाला Result, Objects का एक Sequence होता है, जो या तो एक या एक से अधिक Data Source का Composition होता है या फिर किसी Data Source का Subset होता है। दोनों ही स्थितियों में Return होने वाले Object के Type की जरूरत केवल LINQ Query के कारण होती है। जबकि पूरे Program में अन्‍य किसी स्थान पर Return होने वाले Object के Type की जरूरत नहीं होती।

इस स्थिति में किसी Anonymous Type को Use करने पर हमें किसी ऐसी Class को Define करने की जरूरत नहीं होती, जो केवल LINQ Query से Return होने वाले Outcome को Hold करने के लिए Define की जाए। Anonymous Type को सामान्‍यत: निम्न तरीके से Define किया जाता है:

Anonymous Types in C# - Hindi.

जब हम Anonymous Type Define करते हैं, तो वास्तव में Anonymous Types के Objects के Fields को हमेंशा Object Initialization Syntax का प्रयोग करके Initialize करना होता है।

चूंकि किसी Anonymous Type का कोई नाम नहीं होताए इसलिए हम किसी Anonymous Type के Object को new Operator के साथ Constructor() Name का प्रयोग करके Create नहीं कर सकते हैं। इसलिए Anonymous Type का Object Create करने के लिए हम Invoke होने वाले Constructor को Explicitly Specify नहीं करते, बल्कि हम Object Initialization Syntax का प्रयोग करते हैं।

चूंकि किसी Anonymous Type का कोई नाम नहीं होताए इसलिए हमें Object Initialization Syntax का प्रयोग करके Implicit तरीके से C# Compiler को ये बताना होता है कि हमारे Anonymous Type के Object के Fields कौनसे हैं और उनमें क्या Data Store हो रहा है, जिसे C# Compiler Infer करके Proper Type के Fields Create कर लेता है। जैसे:

var anonyObject = new { Count = 5, Max = 255, Min = 0 }

जब ये Statement Execute होता है, तब Anonymous Expression द्वारा जो Object Create होता है, उसका Reference anonyObject नाम के Object में Store हो जाता है। परिणामस्वरूप यदि हम चाहें, तो इस Newly Create होने वाले Object को निम्नानुसार Statement में Use कर सकते हैं:

Console.WriteLine(“Count is: ” + anonyObject.Count);

Anonymous Type के विषय में ध्‍यान रखने वाली बात ये है कि Anonymous Type के Object का Reference जिस Variable में Store किया जाता है, वह Variable एक प्रकार का Read-Only Public Property बन जाता है। इसलिए इस Identifier को हम पूरे Program में कहीं पर भी उपयोग में ले सकते हैं।

हालांकि हम Anonymous Type नाम को Use करते हैं, लेकिन वास्तव में Crete होने वाला Type पूरी तरह से Anonymous नहीं होता। बल्कि Create होने वाला Type केवल एक Programmer के नजरि, से Anonymous होता है। Internally Compiler स्वयं तो उस Anonymous Type को भी एक Internal नाम Assign करता है। अत: Anonymous Types भी C# के Strong Type Checking Rules को Violate नहीं करते।

जब हम Anonymous Types को Use करते हैं, तब हमें कुछ Rules को Follow करना जरूरी होता है और सबसे पहला Rule ये है कि हमें हमेंशा var Keyword के साथ ही उस Reference Variable को Specify करना चाहिए, जिसमें Newly Create होने वाले Anonymous Type के Object के Reference को Store करना है। जैसे:

Anonymous Types in C# - Hindi.

इसी तरह से Anonymous Types को केवल Local Variables की तरह ही Use किया जा सकता है। यानी हम Anonymous Types को कभी भी किसी Class/Structure के Field Member की तरह Use नहीं कर सकते हैं। साथ ही हम किसी Anonymous Object की Property में किसी अन्‍य Object की Property को Assign नहीं कर सकते, क्योंकि किसी Anonymous Type के लिए Compiler द्वारा Create होने वाली Properties वास्तव में Read-Only Properties होती हैं।

जब हम किसी Anonymous Type के लिए Statement Specify करते हैं और C# Compiler को Anonymous Type Create करने के लिए Object Initializer Syntax प्राप्त होता है, तो C# Compiler एक नया Class Create करता है और उस Class के लिए एक Private Name Construct करता है।

इस Class में Object Initialization Syntax में Use किए गए हर Member के आधार पर एक Read-Only Property Create करता है और उस Property से Associated Field का Type उस Member में Initialize किए गए Data के आधार पर Infer करता है। जबकि Create होने वाली हर Property का नाम वही होता है, जो हम हमारी Object Initialization List में Members का नाम Specify करते हैं। जब एक बार Anonymous Type Construct हो जाता है, तो फिर Compiler उस Type का एक Object Create करता है।

Object Initialization के अलावा Anonymous Type दो और तरीके के Initialization को Support करते हैं, जिसे Simple Identifiers व Member Access Expression के नाम से जाना जाता है। इस तरीके के Initialization को Projection Initializers कहा जाता है, जिसमें Assignment Expression का प्रयोग करने के स्थान पर या तो किसी Identifier को Use किया जाता है या फिर किसी अन्‍य Object के Member को Specify किया जाता है, जिसके Type के अनुसार हमें Anonymous Property Create करना होता है। जैसे:

var student = new { Age = 19, Other.Name, Major };

जब हम Projection Initializers Syntax को Use करते हैं, तब ये जरूरी होता है कि हम जिन Members को Anonymous Type में Initializers की तरह Specify कर रहे हैं, वे Current Program में Anonymous Type Declaration Statement से पहले Defined हों। यदि हम चाहें तो उपरोक्त Code Statement को निम्नानुसार तरीके से Assignment Operator का प्रयोग करते हुए भी Specify कर सकते हैं:

var student = new { Age = Age, Name = Other.Name, Major = Major};

यदि हम एकदम समान Signature का Anonymous Type एक से ज्यादा बार Specify करते हैं, तो C# Compiler Automatically पिछली बार Created Anonymous Type को ही फिर से Reuse कर लेता है। यानी समान Statement या Exactly Matching Statement वाले Anonymous Type को C# फिर से Create नहीं करता। उदाहरण के लिए यदि हम निम्नानुसार Statements लिखें:

var student1 = new { Age = 19, Other.Name, Major };
var student2 = new { Age = Age, Name = Other.Name, Major = Major};

तो C# Compiler दो अलग Anonymous Types Create नहीं करेगा, क्योंकि दोनों ही Anonymous Types का Signature पूरी तरह से एक समान है।

Method Syntax and Query Syntax

C# LINQ हमें मूलत: दो तरीकों से LINQ Queries को Specify करने की सुविधा देता है, जिन्हें Query Syntax व Method Syntax के नाम से जाना जाता है। Method Syntax के अन्तर्गत Standard Method Invocation तरीके को Use किया जाता है। जबकि Query Syntax काफी हद तक SQL Statements के समान ही होते हैं, जिन्हें Query Expression के रूप में लिखा जाता है। जबकि हम हमारी जरूरत के अनुसार इन दोनों को Mix करके भी उपयोग में ले सकते हैं।

Query Syntax एक Declarative तरीका होता है, जिसका मतलब ये होता है कि हमारी Query इस बात को Describe करता है कि हम Data Source से क्या चाहते हैं, लेकिन ये तरीका इस बात को Specify नहीं करता कि हम Data Source से जो Data चाहते हैं, वह Retrieve कैसे होगा। जबकि Method Syntax एक Imperative तरीका होता है, जो Query Method के Execute होने के Exact Order को Specify करता है।

हालांकि Query Syntax द्वारा Expressed Queries को C# Compiler द्वारा Method Invocation Form में ही Translate किया जाता है। इसलिए दोनों ही तरीकों के Execution का Performance से कोई सम्बंध नहीं है और दोनों ही तरीकों से LINQ Query समान तरीके से ही Execute होता है।

File Name: MethodSyntaxAnQuerySyntax.cs
using System;
using System.Linq;

namespace CSharpLINQ
{
    class SimpleQuery
    {
        static void Main()
        {
            int[] numbers = { 2, 5, 28, 31, 17, 16, 42 };
            var numsQuery = from n in numbers where n < 20 select n; 		// Query syntax
            var numsMethod = numbers.Where(x => x < 20); 				// Method syntax
            int numsCount = (from n in numbers where n < 20 select n).Count();	// Combined

            foreach (var x in numsQuery)
                Console.Write("{0}, ", x);

            Console.WriteLine();

            foreach (var x in numsMethod)
                Console.Write("{0}, ", x);
        }
    }
}

// Output:
   2, 5, 17, 16 
   2, 5, 17, 16

जैसाकि इस Program द्वारा हम समझ सकते हैं कि हमने इस Program में Query Syntax को भी Use किया है और Method Syntax को भी और दोनों ही तरीकों से Generate होने वाला Result समान ही होता है। साथ ही हमने इन दोनों तरीकों को Combined Form में भी Use किया है।

Query Syntax के बारे में हमने Chapter की शुरूआत में Discuss किया था, जबकि Method Syntax के बारे में हम आगे Discuss करेंगे। हालांकि जैसाकि हम इस Program के Method Syntax में देख सकते हैं कि हमने Method Syntax में Lambda Expression का प्रयोग किया है।

Query Variables

जब हम कोई LINQ Query Specify करते हैं, तो वह LINQ Query या तो Enumerations के रूप में Results Return करता है, जो उन Items की List Represent करता है, जो Query Parameter को Satisfy करते हैं या फिर एक Single Value Return करता है, जिसे Scalar कहा जाता है और ये Scalar Query को Satisfy करने वाले Results की एक प्रकार की Summary होता है। जैसे:

int[] numbers = { 2, 5, 28 };

// Returns an enumerator
	IEnumerable<int> lowNums = from n in numbers where n < 20 select n;

// Returns an int
	int numsCount = (from n in numbers where n < 20 select n).Count();

यदि हम इस Code Fragment के आधार पर समझें तो इस Code Segment का पहला Statement Integers का एक Array Create करता है जिसमें तीन मान Store होते हैं। इस Array को हमारी अगले Statement के रूप में Specified LINQ Query के लिए Data Source की तरह Use किया जाता है।

दूसरे Statement में हमने एक LINQ Query को Specify किया है जो कि Query को Satisfy करने वाले Elements को Enumerate करता है यानी Query को Satisfy करने वाले Data को numbers नाम के Array Data Source से Return करता है।

जबकि तीसरे Statement द्वारा LINQ Query को Execute किया जाता है और Execution के बाद Count() नाम के LINQ Method को Call किया जाता है, जो Query को Satisfy करते हुए Return होने वाले Items के कुल Count को Return करता है।

इस Code Segment में lowNums numsCount नाम के जो दो Variables Define किए गए हैं, उन्हें ही Query Variable के नाम से जाना जाता है। जो कि किसी LINQ Query की Specification को Represent करते हैं।

हालांकि हमने उपरोक्त Code Segment के दूसरे व तीसरे Statement में lowNums numsCount Variables को Explicitly Declare किया है, लेकिन यदि हम चाहें तो इन्हें var Keyword के माध्‍यम से Implicitly भी Declare कर सकते हैं, जिन्हें Compiler स्वयं ही Compile Time में Appropriate Type में Infer कर लेता है।

जैसाकि हमने पहले भी कहा था कि किसी LINQ Query को किसी Query Variable में Assign कर देने का मतलब ये नहीं है कि Query Variable में Query के Fire होने के बाद Generate होने वाला Result Store हो गया है। बल्कि Query Variable में हमने केवल उस LINQ Query को Specify किया है, जिसे जरूरत होने पर Execute करके Result Generate किया जा सकेगा।

इसलिए जब उपरोक्त Code Segment का दूसरा Statement Execute होता है, तब lowNums नाम के Query Variable में किसी प्रकार का कोई Result नहीं होताए बल्कि केवल Future में Execute होने वाली LINQ Query का Specification होता है।

जबकि numsCount नाम के Variable में वह Actual Integer मान होता है, जो इस बात को Represent करता है कि Data Source के कुल कितने Items तीसरे Statement में Specify की गई LINQ Query में Specified Condition को Satisfy करते हैं और ये संख्‍या केवल तभी प्राप्त हो सकती है, जबकि numsCount के साथ Assigned Specified LINQ Query Execute हो।

इस तरह से यदि सरल शब्दों में कहें तो Query Expression हमेंशा एक Enumeration Return करता है लेकिन Query तब तक Execute नहीं होताए जब तक कि Enumeration Process न हो। जबकि यदि Enumeration कई बार Process हो, तो Query भी कई बार Execute होती है।

साथ ही यदि दुबारा Query Execute होने से पहले Data Source में किसी तरह का परिवर्तन हो, तो Query के दुबारा Execute होने पर हमें Modified Result प्राप्त होता है। जबकि यदि Query Expression कोई Scalar Result Return करता है, Query तुरन्त Execute होती है और Query Execution से Return होने वाला मान Directly Query Variable में Store हो जाता है।

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

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

BUY NOW GET DEMO REVIEWS