C# में एक्सटेंशन प्रॉपर्टीज: जब चाहो, लेकिन नहीं कर सकते (और इसे कैसे दरकिनार करें)
\n\nएक स्थिति की कल्पना करें: आप एक लाइब्रेरी के साथ काम कर रहे हैं, जहाँ क्लास Person में एक प्रॉपर्टी FullName है। सब कुछ ठीक है, लेकिन एक समस्या है — आपको एक गणना योग्य प्रॉपर्टी AgeInDays जोड़नी है, जो जन्म तिथि से दिनों में आयु की गणना करती है। आप एक्सटेंशन मेथड्स के आदी हैं और सोचते हैं: "क्यों न एक्सटेंशन प्रॉपर्टीज बनाया जाए?"
और फिर आप Stack Overflow पर जाते हैं, हज़ारों व्यूज़ वाला एक प्रश्न देखते हैं: "Does C# have extension properties?" — और निराशा के साथ उत्तर पढ़ते हैं: "नहीं, आधिकारिक तौर पर समर्थित नहीं हैं"। लेकिन टैब बंद करने में जल्दबाजी न करें! इस लेख में, हम न केवल यह समझेंगे कि वे क्यों नहीं हैं, बल्कि सुरुचिपूर्ण वर्कअराउंड भी खोजेंगे जो प्रदर्शन में कम नहीं हैं।
\n\nC# एक्सटेंशन प्रॉपर्टीज क्यों नहीं जोड़ता? ऐतिहासिक संदर्भ
\n\nमुख्य बात से शुरू करते हैं: एक्सटेंशन प्रॉपर्टीज कोई सनक नहीं, बल्कि समुदाय का एक लंबे समय से चला आ रहा अनुरोध है। 2016 में GitHub पर एक प्रस्ताव (C# feature request) आया था, लेकिन यह अभी भी लागू नहीं हुआ है। क्यों?
\n\n- \n
- कंपाइलर में जटिलता: मेथड्स के विपरीत, प्रॉपर्टीज में गेटर्स और सेटर्स होते हैं जो किसी विशिष्ट इंस्टेंस से बंधे होने चाहिए। सिंटैक्स स्तर पर इस तर्क का विस्तार करने के लिए कंपाइलर में गंभीर बदलाव की आवश्यकता होती है। \n
- इंडेक्सर्स के साथ विरोध: C# में प्रॉपर्टीज और इंडेक्सर्स आपस में घनिष्ठ रूप से जुड़े हुए हैं। एक्सटेंशन प्रॉपर्टीज जोड़ने से अस्पष्टताएँ पैदा हो सकती हैं। \n
- अन्य फीचर्स को प्राथमिकता: C# टीम ने records, pattern matching और static abstract members (C# 11) पर ध्यान केंद्रित किया, जो अधिकांश परिदृश्यों के लिए अधिक लाभ लाते हैं। \n
लेकिन आधिकारिक समर्थन का अभाव कोई फैसला नहीं है। आइए देखें कि अनुभवी डेवलपर्स इस समस्या को कैसे हल करते हैं।
\n\nएक्सटेंशन मेथड्स: आपका मुख्य उपकरण (लेकिन बारीकियों के साथ)
\n\nसबसे स्पष्ट तरीका प्रॉपर्टीज के बजाय एक्सटेंशन मेथड्स का उपयोग करना है। person.AgeInDays के बजाय आप person.GetAgeInDays() लिखते हैं। यह काम करता है, लेकिन एकरूपता के सिद्धांत का उल्लंघन करता है: बाकी कोड में आप प्रॉपर्टीज का उपयोग करते हैं, और यहाँ अचानक एक मेथड।
public static class PersonExtensions\n{\n public static int GetAgeInDays(this Person person)\n {\n return (DateTime.Now - person.BirthDate).Days;\n }\n}\n\n// उपयोग:\nvar age = person.GetAgeInDays(); // काम करता है, लेकिन सुंदर नहीं\n\n\nनुकसान: कोड कम पठनीय हो जाता है, खासकर LINQ कॉल चेन में। लाभ: प्रदर्शन के दृष्टिकोण से यह पूरी तरह से मुफ्त है — एक्सटेंशन मेथड का कॉल सामान्य स्टैटिक मेथड से अलग नहीं है।
\n\nविकल्प #1: स्टैटिक फैक्ट्रीज़ और सहायक क्लासेस
\n\nयदि आपको एक "प्रॉपर्टी" चाहिए जो डेटा के आधार पर गणना की जाती है, तो आप एक स्टैटिक हेल्पर क्लास बना सकते हैं:
\n\npublic static class PersonHelper\n{\n public static int AgeInDays(Person person) => (DateTime.Now - person.BirthDate).Days;\n}\n\n// उपयोग:\nvar age = PersonHelper.AgeInDays(person);\n\n\nयह एक्सटेंशन मेथड से अधिक ईमानदार है: यह तुरंत स्पष्ट है कि यह एक सहायक फ़ंक्शन है। लेकिन फिर भी प्रॉपर्टी नहीं है।
\n\nविकल्प #2: एट्रीब्यूट्स और कोड जनरेशन (Source Generators)
\n\nजटिल परिदृश्यों के लिए (जैसे, NuGet पैकेज से क्लासेस में प्रॉपर्टीज जोड़ना), आप source generators का उपयोग कर सकते हैं। वे .NET 5 में दिखाई दिए और कंपाइलेशन के दौरान कोड उत्पन्न करने की अनुमति देते हैं। आप एक एट्रीब्यूट लिखते हैं, और जनरेटर आवश्यक प्रॉपर्टीज के साथ एक partial-क्लास बनाता है।
\n\n[AutoExtensionProperty(typeof(Person), nameof(Person.BirthDate))]\npublic partial class PersonExtensions\n{\n // जनरेटर प्रॉपर्टी AgeInDays बनाएगा\n}\n\n// उत्पन्न कोड:\npublic partial class PersonExt