C# में एडवांस्ड इंटरव्यू: एम्प्लॉयर को कैसे प्रभावित करें और सफल हों
\n\nSenior या Middle .NET डेवलपर पद के लिए इंटरव्यू सिर्फ सिंटैक्स की जांच नहीं है। इंटरव्यूअर प्लेटफॉर्म की आंतरिक कार्यप्रणाली की गहरी समझ, परफॉरमेंट कोड लिखने की क्षमता और आर्किटेक्चरल निर्णय लेने की क्षमता देखना चाहते हैं। इस लेख में, हम उन प्रमुख विषयों और एडवांस्ड लेवल के प्रश्नों पर चर्चा करेंगे जो आपको C# का टेक्निकल इंटरव्यू पास करने में मदद करेंगे।
\n\n1. असिंक्रोनस प्रोग्रामिंग: async/await और Task
\n\nयह शायद इंटरव्यू में सबसे लोकप्रिय विषय है। केवल यह कहना पर्याप्त नहीं है कि आप async/await जानते हैं। आपको यह समझना होगा कि यह अंदरूनी रूप से कैसे काम करता है।
प्रश्न: SynchronizationContext क्या है और यह await के निष्पादन को कैसे प्रभावित करता है?
\nयह एक क्लासिक प्रश्न है। SynchronizationContext एक एब्स्ट्रैक्शन है जो एक विशिष्ट संदर्भ (जैसे, WPF का UI थ्रेड या ASP.NET का थ्रेड पूल) में कोड के निष्पादन को शेड्यूल करने की अनुमति देता है। जब आप await का उपयोग करते हैं, तो असिंक्रोनस ऑपरेशन पूरा होने के बाद कोड डिफ़ॉल्ट रूप से मूल संदर्भ में वापस आने का प्रयास करता है। कंसोल एप्लिकेशन में यह थ्रेड पूल है, जबकि UI में यह डिस्पैचर थ्रेड है। इस तंत्र को समझने से डेडलॉक से बचने में मदद मिलती है।
प्रश्न: Task.Run और Task.Factory.StartNew में क्या अंतर है?
\nपहली नज़र में ये समान लगते हैं, लेकिन Task.Run एक सरलीकृत रैपर है। Task.Factory.StartNew अधिक नियंत्रण देता है (जैसे, TaskCreationOptions या TaskScheduler सेट करना)। हालांकि, डिफ़ॉल्ट रूप से Task.Run TaskScheduler.Default (थ्रेड पूल) का उपयोग करता है, जबकि Task.Factory.StartNew वर्तमान शेड्यूलर का उपयोग कर सकता है, जो कभी-कभी अप्रत्याशित व्यवहार का कारण बनता है।
// SynchronizationContext के कारण डेडलॉक का उदाहरण (UI एप्लिकेशन में)\npublic async Task<string> GetDataAsync()\n{\n var result = await SomeAsyncMethod(); // संदर्भ कैप्चर करना\n return result.ToString(); // UI थ्रेड में वापस आने का प्रयास\n}\n\n// यदि टास्क पर .Result या .Wait() कॉल किया जाए, तो डेडलॉक होगा\nvar data = GetDataAsync().Result; // खराब अभ्यास!\n\n\n2. मेमोरी मैनेजमेंट और Garbage Collector (GC)
\n\nएक एडवांस्ड डेवलपर को यह समझना चाहिए कि .NET मेमोरी का प्रबंधन कैसे करता है, ताकि मेमोरी लीक से बचा जा सके और परफॉरमेंस को ऑप्टिमाइज़ किया जा सके।
\n\nप्रश्न: GC की पीढ़ियों (Gen 0, Gen 1, Gen 2) और Large Object Heap (LOH) की व्याख्या करें।
\n.NET में GC एक पीढ़ीगत मॉडल का उपयोग करता है। ऑब्जेक्ट पहले Gen 0 में आते हैं (यहां संग्रह बार-बार होता है)। यदि वे संग्रह से बच जाते हैं, तो वे Gen 1, फिर Gen 2 में चले जाते हैं। LOH 85,000 बाइट्स से बड़े ऑब्जेक्ट के लिए है। यह डिफ़ॉल्ट रूप से संपीड़ित नहीं होता (.NET 4.5.1 से पहले), जिससे फ्रैग्मेंटेशन हो सकता है। प्रश्न को और जटिल बनाया जा सकता है: "बैकग्राउंड गार्बेज कलेक्शन कैसे काम करता है?" या "GC मोड क्या हैं: Workstation बनाम Server?"
\n\nप्रश्न: फाइनलाइज़ेशन क्या है और इससे संबंधित समस्याओं से कैसे बचें?
\nफाइनलाइज़र (~Finalizer()) गार्बेज कलेक्शन को धीमा कर देते हैं, क्योंकि फाइनलाइज़र वाले ऑब्जेक्ट फाइनलाइज़ेशन कतार में आते हैं और उन्हें GC के दो पास की आवश्यकता होती है। सही पैटर्न Dispose पैटर्न के साथ IDisposable को लागू करना है।
public class ResourceHolder : IDisposable\n{\n private IntPtr _handle;\n private bool _disposed = false;\n\n public void Dispose()\n {\n Dispose(true);\n GC.SuppressFinalize(this);\n }\n\n protected virtual void Dispose(bool disposing)\n {\n if (!_disposed)\n {\n if (disposing)\n {\n // प्रबंधित संसाधनों को मुक्त करें\n }\n // अप्रबंधित संसाधनों (handle) को मुक्त करें\n _disposed = true;\n }\n }\n\n ~ResourceHolder()\n {\n Dispose(false);\n }\n}\n\n\n3. डेलीगेट, इवेंट और LINQ: सिंटैक्स से समझ तक
\n\nये विषय अक्सर