كيف تجتاز مقابلة C#: أهم الأسئلة المتقدمة

مدرب بايثون أونلاين للمبتدئين

تعلم Python بسهولة دون إرهاق نظري. حل مهام عملية مع التحقق التلقائي واكتب الكود مباشرة في المتصفح.

ابدأ الدورة

كيف تجتاز مقابلة C#: أهم الأسئلة المتقدمة



مقابلة منصب مطور Senior C# لا تختبر فقط بناء الجملة، بل الفهم العميق للبنية الداخلية لـ .NET، تحسين الأداء والقرارات المعمارية. في هذه المقالة، سنستعرض المواضيع الرئيسية التي تظهر غالباً في المقابلات التقنية. ستتعلم كيفية الإجابة على الأسئلة الصعبة، وستحصل على أمثلة كود جاهزة لإظهار مهاراتك.



1. البرمجة غير المتزامنة: async/await و Task



الأسئلة حول async و await هي كلاسيكية في أي مقابلة متقدمة. يريد المحاورون رؤية أنك تفهم كيفية عمل سياق التزامن وتجنب حالات الجمود (deadlock).



سؤال نموذجي: "ماذا يحدث إذا استدعيت .Result أو .Wait() على طريقة غير متزامنة في سلسلة واجهة المستخدم (UI)؟"



الإجابة: سيحدث deadlock، لأن السلسلة الرئيسية ستحظر انتظار النتيجة، بينما سيحاول استمرار الطريقة غير المتزامنة (continuation) العودة إلى نفس سياق التزامن المشغول. الحل هو استخدام ConfigureAwait(false) أو جعل الاستدعاء غير متزامن بالكامل.



public async Task<string> GetDataAsync(){    // العمل الصحيح مع السياق    var result = await SomeHttpCallAsync().ConfigureAwait(false);    return result;}

// خطأ: deadlock في UI/ASP.NET Core (قبل .NET Core 2.1)// var data = GetDataAsync().Result;


سؤال إضافي: "ما الفرق بين Task.Run و Task.Factory.StartNew؟"



Task.Run يستخدم تجمع الخيوط الافتراضي ويفك المهام المتداخلة تلقائياً. StartNew يعطي تحكماً أكبر (مثل تحديد TaskCreationOptions.LongRunning)، لكنه يتطلب إدارة يدوية لـ Unwrap() للمفوضين غير المتزامنين.



2. LINQ والتنفيذ المؤجل (Deferred Execution)



LINQ أداة قوية، لكن استخدامها الخاطئ قد يؤدي إلى تدهور الأداء. الأسئلة المتقدمة غالباً ما تتعلق بـ IQueryable مقابل IEnumerable وتحقيق الاستعلامات.



سؤال: "لماذا يقوم الكود التالي بعدة استعلامات إلى قاعدة البيانات؟"



var query = context.Products.Where(p => p.Price > 100);foreach (var product in query){    Console.WriteLine(product.Name);}var count = query.Count(); // الاستعلام الثاني!


الإجابة: IQueryable يمثل تعبيراً (Expression Tree) يُترجم إلى SQL. في كل مرة تقوم بالتكرار أو استدعاء دالة تجميعية (Count, Sum)، يتم إرسال SQL من جديد. لتجنب ذلك، يجب تحقيق البيانات: var list = query.ToList();



فارق دقيق متقدم: الفرق بين First() و FirstOrDefault() — First() يرمي استثناءً إذا كانت التسلسل فارغاً، مما قد يكون أكثر تكلفة من حيث معالجة الأخطاء.



3. إدارة الذاكرة وجامع القمامة (GC)



فهم عمل GC هو علامة على مطور Senior. قد تتعلق الأسئلة بالأجيال (Generations)، الإنهاء (Finalization) ونمط Dispose.



سؤال: "ما هو Large Object Heap (LOH) ولماذا يجب الحذر معه؟"



الإجابة: LOH هو كومة للكائنات التي يزيد حجمها عن 85,000 بايت. على عكس Small Object Heap، لا يخضع LOH للضغط (حتى .NET 4.5.1)، مما يؤدي إلى تجزئة الذاكرة. قد يتسبب ذلك في OutOfMemoryException حتى لو كانت الذاكرة الحرة كثيرة. التوصيات: استخدام تجمعات الكائنات أو تقسيم المصفوفات الكبيرة إلى أجزاء.



// مثال على ممارسة سيئةbyte[] largeBuffer = new byte[100_000]; // يقع في LOH

// الأفضل: استخدام ArrayPoolbyte[]

المدونات

توصيات الكتب