معالجة الأخطاء في C#: try/catch وما بعدها: من الألف إلى الياء
أي تطبيق، حتى لو كتبه مطور متمرس، قد يواجه مواقف غير متوقعة: انقطاع الشبكة، عدم وجود ملف على القرص، القسمة على صفر أو إدخال بيانات غير صحيح. في C# (.NET) لإدارة مثل هذه المواقف، يتم استخدام آلية الاستثناءات (exceptions). في هذه المقالة، سنشرح كل ما تحتاج معرفته عن معالجة الأخطاء: من البنية الأساسية try/catch إلى إنشاء أنواع الاستثناءات الخاصة بك وأفضل الممارسات الحديثة.
1. الأساسيات: بنية try/catch/finally
في C#، تتركز معالجة الأخطاء حول ثلاث كتل رئيسية: try و catch و finally.
- try — يحتوي على الكود الذي قد يلقي استثناءً.
- catch — يلتقط ويعالج استثناءً معينًا.
- finally — يتم تنفيذه دائمًا، بغض النظر عن وجود استثناء أم لا (عادةً لتحرير الموارد).
try{ int[] numbers = { 1, 2, 3 }; Console.WriteLine(numbers[5]); // IndexOutOfRangeException}catch (IndexOutOfRangeException ex){ Console.WriteLine($"خطأ: {ex.Message}");}finally{ Console.WriteLine("يتم تنفيذ كتلة finally دائمًا.");}يمكنك استخدام عدة كتل catch لأنواع مختلفة من الاستثناءات. تتم المعالجة من الأعلى إلى الأسفل، لذا يجب وضع الاستثناءات الأكثر تحديدًا فوق الاستثناءات العامة.
try{ // كود خطير}catch (DivideByZeroException ex){ Console.WriteLine("القسمة على صفر!");}catch (Exception ex) // التقاط عام{ Console.WriteLine($"حدث خطأ: {ex.Message}");}2. إلقاء الاستثناءات: عامل throw
أحيانًا تحتاج إلى الإبلاغ صراحة عن موقف غير صحيح. لهذا، يتم استخدام عامل throw. يمكنك إلقاء استثناء قياسي أو استثناء خاص بك.
public void ValidateAge(int age){ if (age < 0 || age > 150) { throw new ArgumentOutOfRangeException(nameof(age), "يجب أن يكون العمر بين 0 و 150."); } Console.WriteLine("العمر صحيح.");}يوجد أيضًا بناء throw; (بدون وسائط) - يُستخدم داخل كتلة catch لـ إعادة إلقاء نفس الاستثناء. هذا مفيد عندما تريد تسجيل الخطأ في السجل، لكنك لا تريد قمعه.
try{ // كود}catch (Exception ex){ Log.Error(ex); // تسجيل في السجل throw; // إعادة إلقاء - الاستثناء يستمر في الانتشار}3. إنشاء استثناءات مخصصة (Custom Exceptions)
بالنسبة لمنطق الأعمال، غالبًا ما يكون من الأسهل استخدام أنواع الاستثناءات الخاصة بك. هذا يجعل الكود أكثر قابلية للقراءة ويسمح بمعالجة الأخطاء المحددة بدقة.
قواعد إنشاء استثناء مخصص:
- توارث الفئة من
Exception(أو منApplicationException، لكن الأفضل منException). - تنفيذ ثلاثة منشئين قياسيين (بدون معلمات، مع رسالة، مع رسالة واستثناء داخلي).
- يوصى بإضافة اللاحقة
Exceptionإلى اسم الفئة.
public class UserNotFoundException : Exception{ public UserNotFoundException() { }
public UserNotFoundException(string message) : base(message) { }
public UserNotFoundException(string message, Exception inner) : base(message, inner) { }}
// الاستخدامthrow new UserNotFoundException("المستخدم ذو المعرف 123 غير موجود.");4. أفضل الممارسات: كيف لا تؤذي نفسك والمشروع
معالجة الأخطاء ليست مجرد تغليف كل شيء في try/catch. إليك بعض القواعد الذهبية التي يجب اتباعها في C# (.NET):