C# में Generics: इनकी आवश्यकता क्यों है और व्यवहार में कैसे उपयोग करें
\n\nGenerics (सामान्यीकरण) — C# भाषा की एक प्रमुख क्षमता है, जो लचीला, पुन: प्रयोज्य और प्रकार-सुरक्षित कोड लिखने की अनुमति देती है। इस लेख में, हम समझेंगे कि सामान्यीकरण क्यों आवश्यक हैं, वे अंदरूनी रूप से कैसे काम करते हैं, और वास्तविक परियोजनाओं में उनके उपयोग के व्यावहारिक उदाहरण दिखाएंगे।
\n\nGenerics क्या हैं और इनकी आवश्यकता क्यों है?
\n\nकल्पना करें कि आपको एक ऐसी विधि लागू करनी है जो दो मानों को आपस में बदलती है। सामान्यीकरण के बिना, आपको प्रत्येक डेटा प्रकार के लिए अलग-अलग संस्करण लिखने होंगे:
\n\n// Generics के बिना — कोड का दोहराव\nvoid SwapInt(ref int a, ref int b) { int temp = a; a = b; b = temp; }\nvoid SwapString(ref string a, ref string b) { string temp = a; a = b; b = temp; }\n// ... और इसी तरह प्रत्येक प्रकार के लिए\n\nGenerics के साथ यह समस्या सुंदर ढंग से हल हो जाती है:
\n\n// Generics के साथ — सभी प्रकारों के लिए एक विधि\nvoid Swap<T>(ref T a, ref T b)\n{\n T temp = a;\n a = b;\n b = temp;\n}\n\n// उपयोग\nint x = 1, y = 2;\nSwap(ref x, ref y); // T = int\n\nstring s1 = "Hello", s2 = "World";\nSwap(ref s1, ref s2); // T = string\n\nGenerics के मुख्य लाभ:
\n- \n
- प्रकार सुरक्षा — प्रकार की त्रुटियाँ संकलन चरण पर ही पकड़ी जाती हैं \n
- प्रदर्शन — मूल्य प्रकारों के लिए बॉक्सिंग/अनबॉक्सिंग का अभाव \n
- कोड पुन: उपयोग — एक वर्ग/विधि किसी भी प्रकार के साथ काम करता है \n
- पठनीयता — कोड अधिक स्पष्ट और संक्षिप्त हो जाता है \n
Generic-वर्ग और संरचनाएँ
\n\nGenerics के उपयोग का सबसे सामान्य उदाहरण संग्रह (collections) हैं। प्रत्येक प्रकार के लिए अपना वर्ग लिखने के बजाय, हम एक सामान्यीकृत वर्ग बनाते हैं:
\n\npublic class MyList<T>\n{\n private T[] _items;\n private int _count;\n\n public MyList(int capacity = 4)\n {\n _items = new T[capacity];\n _count = 0;\n }\n\n public void Add(T item)\n {\n if (_count == _items.Length)\n {\n Array.Resize(ref _items, _items.Length * 2);\n }\n _items[_count++] = item;\n }\n\n public T Get(int index)\n {\n if (index < 0 || index >= _count)\n throw new IndexOutOfRangeException();\n return _items[index];\n }\n\n public int Count => _count;\n}\n\n// उपयोग\nvar numbers = new MyList<int>();\nnumbers.Add(10);\nnumbers.Add(20);\n\nvar names = new MyList<string>();\nnames.Add("Alice");\n\nध्यान दें: इंस्टेंस बनाते समय हम कोण कोष्ठक <T> में विशिष्ट प्रकार निर्दिष्ट करते हैं। संकलक इस प्रकार को उन सभी स्थानों पर प्रतिस्थापित करता है जहाँ T का उपयोग किया गया है।
Generic-विधियाँ और बाधाएँ (constraints)
\n\nकभी-कभी प्रकार T पर बाधाएँ लगाने की आवश्यकता होती है। उदाहरण के लिए, यह सुनिश्चित करने के लिए कि प्रकार एक निश्चित इंटरफ़ेस लागू करता है या उसके पास बिना पैरामीटर वाला कंस्ट्रक्टर है:
// बाधा: T को IComparable<T> लागू करना होगा\npublic T GetMax<T>(T a, T b) where T : IComparable<T>\n{\n return a.CompareTo(b) > 0 ? a : b;\n}\n\n// बाधा: T के पास बिना पैरामीटर वाला कंस्ट्रक्टर होना चाहिए\npublic class Factory<T> where T : new()\n{\n public T Create()\n {\n return new T();\n }\n}\n\n// बाधा: T एक मूल्य प्रकार (struct) होना चाहिए\npublic struct Nullable<T> where T : struct\n{\n private T _value;\n private bool _hasValue;\n\n public Nullable(T value)\n {\n _value = value;\n _hasValue = true;\n }\n\n public T Value => _hasValue ? _value : throw new InvalidOperationException();\n public bool HasValue => _hasValue;\n}\n\nबाधाओं के मुख्य प्रकार:
\n- \n
where T : class— संदर्भ प्रकार \n where T : struct— मूल्य प्रकार \n ब्लॉग
पुस्तक अनुशंसाएँ
यह भी पढ़ें