8 तथ्य जिन्हें आप C # के बारे में नहीं जानते होंगे

यहाँ C # भाषा के बारे में कुछ असामान्य तथ्य दिए गए हैं जिनके बारे में कुछ डेवलपर्स को पता है।

1. इंडेक्स परमाम मापदंडों का उपयोग कर सकते हैं


हम सभी जानते हैं कि x = कुछ ["a"] इंडेक्सर्स आमतौर पर देखते हैं, साथ ही इसे लागू करने के लिए आवश्यक कोड:

public string this[string key] { get { return internalDictionary[key]; } } 

लेकिन क्या आप जानते हैं कि जिन तत्वों का उपयोग करने के लिए आप पैरामीटर पैरामीटर x = कुछ ["a", "b", "c", "d"] का उपयोग कर सकते हैं?
बस अपना अनुक्रमणिका इस प्रकार लिखें:

 public IEnumerable<string> this[params string[] keys] { get { return keys.Select(key => internalDictionary[key]).AsEnumerable(); } } 

बड़ी खबर यह है कि आप एक ही कक्षा में एक साथ कई इंडेक्सर्स का उपयोग कर सकते हैं। यदि कोई पैरामीटर के रूप में एक सरणी या कई तर्कों को पारित करता है, तो उसे परिणामस्वरूप IEnumerable मिलेगा, लेकिन कॉल करने से, एक पैरामीटर के साथ एक अनुक्रमणिका, उसे एक ही मूल्य मिलेगा।

2. आपके कोड में परिभाषित स्ट्रिंग शाब्दिक एक ही प्रतिलिपि में संग्रहीत हैं


कई डेवलपर्स निम्नलिखित कोड सोचते हैं:

 if (x == "" || x == "y") 

हर बार एक दो लाइनें बनाएगा। नहीं, यह नहीं होगा। C #, कई अन्य प्रोग्रामिंग भाषाओं की तरह, स्ट्रिंग इंटर्निंग का उपयोग करता है, और आपके एप्लिकेशन में उपयोग किए जाने वाले प्रत्येक शाब्दिक स्ट्रिंग को एक विशेष सूची (हैश टेबल) में रखा जाता है, जिसे एक स्ट्रिंग पूल कहा जाता है, जहां से रनटाइम में इसका लिंक लिया जाता है।

आप यह निर्धारित करने के लिए String.IsInterned पद्धति का उपयोग कर सकते हैं कि कोई स्ट्रिंग इस समय इंटर्नमेंट पूल में है, लेकिन याद रखें कि String.IsInterned ("क्या") == "क्या" हमेशा सही रहेगा।
String.IsInterned ("wh" + "at") == "क्या" भी हमेशा सही होगा, अनुकूलन के लिए संकलक का धन्यवाद। String.IsInterned (नया स्ट्रिंग (नया char [] {'w', 'h', 'a', 't'}) == नया string (नया char [] {'w', 'h', 'a') , 't'}) केवल तभी सच होगा जब शाब्दिक स्ट्रिंग "क्या" पहले से ही आपके कोड में उपयोग किया गया है या यदि इसे मैन्युअल रूप से इंटर्नमेंट पूल में जोड़ा गया था।

यदि आपके पास ऐसी कक्षाएं हैं जो नियमित रूप से स्ट्रिंग्स का उपयोग करती हैं, तो उन्हें स्ट्रिंग पूल में जोड़ने के लिए String.Internate विधि का उपयोग करने पर विचार करें। हालांकि, सावधान रहें, क्योंकि इस मामले में वे आवेदन समाप्त होने तक संग्रहीत किए जाते हैं, इसलिए स्ट्रिंग का उपयोग करें। सावधानी से ध्यान दें। पूल में एक स्ट्रिंग जोड़ने के लिए, बस String.Intern (someClass.ToString ()) विधि को कॉल करें। एक और एहतियात है कि (वस्तु) "हाय" == (वस्तु) "हाय" हमेशा सच है, इंटर्निंग के लिए धन्यवाद। इस कोड को व्याख्या विंडो में जांचने की कोशिश करें, और परिणाम नकारात्मक होगा, क्योंकि डिबगर आपकी लाइनों को नजरअंदाज नहीं करता है।

3. कम विशिष्ट लोगों के लिए कास्टिंग प्रकार आपको उनके वास्तविक प्रकार का उपयोग करने से नहीं रोकता है


इसका एक शानदार उदाहरण एक ऐसी संपत्ति है जो IEnumerable को लौटाती है, जिसका वास्तविक प्रकार सूची है, उदाहरण के लिए:

 private readonly List<string> internalStrings = new List<string>(); public IEnumerable<string> AllStrings { get { return internalStrings; } 

आपको लगता है कि कोई भी तार की सूची नहीं बदल सकता है। काश, यह करना बहुत आसान है:

 ((List<string>)x.AllStrings).Add("Hello"); 

यहां तक ​​कि आसन विधि भी यहां मदद नहीं करेगी। आप AsReadOnly विधि का उपयोग कर सकते हैं, जो सूची में एक आवरण बना देगा और हर बार जब आप इसे बदलने की कोशिश करते हैं तो एक अपवाद फेंक देंगे, हालांकि यह आपकी कक्षाओं के साथ समान चीजों के लिए एक अच्छा पैटर्न भी प्रदान करता है।

4. तरीकों में चर घुंघराले ब्रेसिज़ द्वारा सीमित एक गुंजाइश हो सकती है


पास्कल प्रोग्रामिंग भाषा में, आपको उन सभी चरों का वर्णन करना होगा जो आपके फ़ंक्शन की शुरुआत में उपयोग किए जाएंगे। सौभाग्य से, आज चर घोषणाएं उनके असाइनमेंट के बगल में मौजूद हो सकती हैं, जो आपको इरादा करने से पहले गलती से इस्तेमाल होने से रोकता है।

हालाँकि, यह आपको इनका उपयोग करने से नहीं रोकता है क्योंकि इन्हें अब आवश्यकता नहीं है। हम कीवर्ड के लिए / अगर / जबकि / का उपयोग करके अस्थायी चर का वर्णन कर सकते हैं। आपको आश्चर्य होगा, लेकिन आप समान परिणाम प्राप्त करने के लिए कीवर्ड के बिना घुंघराले ब्रेसिज़ का उपयोग करके अस्थायी चर का भी वर्णन कर सकते हैं:

 private void MultipleScopes() { { var a = 1; Console.WriteLine(a); } { var b = 2; Console.WriteLine(a); } } 

यह कोड दूसरी पंक्ति के कारण संकलन नहीं करता है, क्योंकि यह एक चर को संदर्भित करता है जो ब्रेसिज़ में संलग्न है। घुंघराले ब्रेस के साथ भागों में विधि का ऐसा विभाजन काफी उपयोगी है, लेकिन एक बेहतर उपाय यह है कि विधि को रिफैक्टिंग विधि का उपयोग करके छोटे लोगों में विभाजित किया जाए: विधि निकालना।

5. गणना में विस्तार विधियां हो सकती हैं


एक्सटेंशन विधियाँ मौजूदा कक्षाओं के लिए विधियाँ लिखने की क्षमता प्रदान करती हैं ताकि आपकी टीम के लोग उनका उपयोग कर सकें। यह देखते हुए कि गणनाएं कक्षाओं के समान हैं (अधिक सटीक, संरचनाएं), आपको आश्चर्य नहीं होना चाहिए कि उन्हें बढ़ाया जा सकता है, उदाहरण के लिए:

 enum Duration { Day, Week, Month }; static class DurationExtensions { public static DateTime From(this Duration duration, DateTime dateTime) { switch (duration) { case Duration.Day: return dateTime.AddDays(1); case Duration.Week: return dateTime.AddDays(7); case Duration.Month: return dateTime.AddMonths(1); default: throw new ArgumentOutOfRangeException("duration"); } } } 

मुझे लगता है कि गणना में बुराई है, लेकिन कम से कम विस्तार के तरीकों से आपके कोड में कुछ सशर्त जांच (स्विच / यदि) से छुटकारा मिल सकता है। यह जांचना याद रखें कि गणना मूल्य सही सीमा में है।

6. जिस क्रम में आप स्थिर चर मामलों का वर्णन करते हैं


कुछ लोग दावा करते हैं कि चर वर्णमाला के क्रम में व्यवस्थित होते हैं, और विशेष उपकरण हैं जो आपके लिए उनके आदेश को बदल सकते हैं। हालाँकि, एक परिदृश्य है जिसमें पुन: व्यवस्थित करने से आपका एप्लिकेशन टूट सकता है।

 static class Program { private static int a = 5; private static int b = a; static void Main(string[] args) { Console.WriteLine(b); } } 

यह कोड 5 नंबर को प्रिंट करेगा। अगर आप a और b के वेरिएबल्स का विवरण स्वैप करते हैं, तो यह 0 प्रिंट होगा।

7. निजी वर्ग का उदाहरण चर इस वर्ग के दूसरे उदाहरण में उपलब्ध हो सकता है


आप सोच सकते हैं कि निम्नलिखित कोड काम नहीं करेगा:

 class KeepSecret { private int someSecret; public bool Equals(KeepSecret other) { return other.someSecret == someSecret; } } 

यह सोचना आसान है कि निजी का मतलब केवल एक वर्ग का दिया गया उदाहरण है, उस तक पहुंच हो सकती है, लेकिन वास्तव में इसका मतलब है कि केवल इस वर्ग की पहुंच है ... जिसमें इस वर्ग के अन्य उदाहरण भी शामिल हैं। वास्तव में, कुछ तुलना विधियों को लागू करते समय यह बहुत उपयोगी है।

8. सी # भाषा विनिर्देश आपके कंप्यूटर पर पहले से ही


यदि आपके पास Visual Studio स्थापित है, तो आप VC # \ विनिर्देश फ़ोल्डर में विनिर्देश पा सकते हैं। VS 2011 वर्ड प्रारूप में C # 5.0 भाषा विनिर्देश के साथ आता है।

यह कई दिलचस्प तथ्यों से भरा है जैसे:


और आपमें से जो कहते हैं, "मैं यह सब जानता था / सबसे अधिक," मैं कहता हूं, "जब आप डेवलपर्स को किराए पर लेते हैं तो आप कहां होते हैं?" गंभीरता से, भाषा के अच्छे ज्ञान के साथ C # डेवलपर को ढूंढना काफी कठिन है।

अपने आप से मैं कुछ तथ्यों को जोड़ूंगा:

9. आप किसी एन्यूमरेशन में एक स्थिर नाम मान का उपयोग नहीं कर सकते हैं


मुझे लगता है कि यह तथ्य कई डेवलपर्स को पता है। यह समझने के लिए कि यह जानना पर्याप्त है कि गणना क्या संकलित है।

निम्नलिखित सूची:

 public enum Language { C, Pascal, VisualBasic, Haskell } 

संकलक कुछ इस तरह से देखता है:

 public struct Language : Enum { // ,      public const Language C = (Language)0; public const Language Pascal = (Language)1; public const Language VisualBasic = (Language)2; public const Language Haskell = (Language)3; //      Language //        public Int32 value__; } 

अब यह स्पष्ट है कि चर नाम value__ केवल गणना के वर्तमान मूल्य को संग्रहीत करने के लिए आरक्षित है।

10. क्षेत्र इनिशियलाइज़र बहुत अधिक अनुमति देता है


हम सभी जानते हैं कि फील्ड इनिशियलाइज़र कैसे काम करता है।

 class ClassA { public string name = "Tim"; public int age = 20; public ClassA() { } public ClassA(string name, int age) { this.name = name; this.age = age; } } 

इनिशियलाइज़ेशन कोड बस प्रत्येक कंस्ट्रक्टर में रखा जाता है।

 class ClassA { public string name; public int age; public ClassA() { this.name = "Tim"; this.age = 20; base..ctor(); } public ClassA(string name, int age) { this.name = "Tim"; this.age = 20; base..ctor(); this.name = name; this.age = age; } } 

लेकिन अगर एक कंस्ट्रक्टर दूसरे को कॉल करता है, तो इनिशियलाइज़ेशन को केवल तथाकथित कंस्ट्रक्टर में रखा जाता है ...

 class ClassA { public string name = "Tim"; public int age = 20; public ClassA() { } public ClassA(string name, int age):this() { this.name = name; this.age = age; } } 

जो बराबर है

 class ClassA { public string name; public int age; public ClassA() { this.name = "Tim"; this.age = 20; base..ctor(); } public ClassA(string name, int age) { this..ctor(); this.name = name; this.age = age; } } 

और अब सवाल यह है कि अगर डिजाइनर एक-दूसरे को बुलाते हैं तो क्या होता है? कंपाइलर इनिशियलाइज़ेशन कोड डालने का निर्णय कहाँ करता है?

उत्तर: कंपाइलर तय करेगा कि चूंकि पहला कंस्ट्रक्टर दूसरे को कॉल करता है, इसलिए मैं पहले में इनिशियलाइज़ेशन नहीं डालूंगा। वह दूसरे डिजाइनर के साथ इसी तरह के निष्कर्ष निकालेंगे। नतीजतन, आरंभीकरण कोड को किसी भी निर्माता में नहीं रखा जाएगा ... और चूंकि इसे कहीं भी रखने की आवश्यकता नहीं है, तो त्रुटियों के लिए इसकी जांच क्यों की जानी चाहिए? इस प्रकार, इनिशियलाइज़ेशन कोड में, आप जो चाहें लिख सकते हैं। उदाहरण के लिए

 class ClassA { public string name = 123456789; public int age = string.Empty; public ClassA():this("Alan", 25) { } public ClassA(string name, int age):this() { this.name = name; this.age = age; } } 

यह कोड समस्याओं के बिना संकलित करता है, लेकिन इस वर्ग का एक उदाहरण बनाते समय यह एक स्टैक ओवरफ्लो के साथ दुर्घटनाग्रस्त हो जाता है।

11. आप बेस एन्यूमरेशन का वर्णन करते समय केवल C # समानार्थी शब्द का उपयोग कर सकते हैं


जैसा कि आप जानते हैं, किसी गणना का वर्णन करते समय, हम स्पष्ट रूप से अंतर्निहित आधार प्रकार को इंगित कर सकते हैं। डिफ़ॉल्ट इंट है।

हम इस तरह लिख सकते हैं

 public enum Language : int { C, Pascal, VisualBasic, Haskell } 

हालाँकि हम ऐसा नहीं लिख सकते

 public enum Language : Int32 { C, Pascal, VisualBasic, Haskell } 

कंपाइलर को C # टाइप पर्यायवाची की आवश्यकता होती है।

12. संग्रह में उपयोग किए जाने पर संरचनाएं अपरिवर्तनीय हैं


जैसा कि आप जानते हैं, .NET में संरचनाएं महत्वपूर्ण प्रकार हैं, अर्थात्, वे मूल्य (प्रतिलिपि) द्वारा पारित किए जाते हैं, यही वजह है कि परस्पर संरचनाएं बुराई हैं। हालांकि, यह तथ्य कि परिवर्तनशील संरचनाएं दुष्ट हैं, इसका मतलब यह नहीं है कि उन्हें बदला नहीं जा सकता है। डिफ़ॉल्ट रूप से, संरचनाएं परिवर्तनशील होती हैं, अर्थात, उनकी स्थिति को बदला जा सकता है। लेकिन अगर संरचनाओं को संग्रहों में उपयोग किया जाता है, तो वे पारस्परिक रूप से बंद हो जाते हैं। कोड पर विचार करें:

 struct Point { public int x; public int y; } static void Main(string[] args) { var p = new Point(); px = 5; py = 9; var list = new List<Point>(10); list.Add(p); list[0].x = 90;//  var array = new Point[10]; array[0] = p; array[0].x = 90;//  } 

पहले मामले में, हमें एक संकलन त्रुटि मिलती है, क्योंकि संग्रह अनुक्रमणिका केवल एक विधि है जो हमारी संरचना की एक प्रति लौटाती है। दूसरे मामले में, हमें एक त्रुटि नहीं मिली है, क्योंकि सरणियों में अनुक्रमण एक विधि कॉल नहीं है, लेकिन सही तत्व के लिए एक अपील है।

पढ़ने के लिए धन्यवाद।
मुझे उम्मीद है कि यह लेख मददगार रहा है।

Source: https://habr.com/ru/post/In178763/


All Articles