مقدمة في معالجة الأخطاء في C#
في أي تطبيق، وخاصة في الأنظمة المؤسسية المعقدة على منصة .NET، الأخطاء حتمية. قد يقوم المستخدم بإدخال بيانات غير صحيحة، أو قد يكون الملف غير متاح، أو قد ينقطع الاتصال بالشبكة. بدلاً من السماح للبرنامج بالانهيار، يستخدم المطور الماهر آلية معالجة الاستثناءات.
في C#، أساس هذه الآلية هو بناء try/catch/finally. ومع ذلك، فإن إمكانيات اللغة لا تقتصر على هذا: هناك عوامل using و throw، بالإضافة إلى إمكانية إنشاء أنواع استثناءات مخصصة. في هذه المقالة، سنقوم بتحليل جميع الجوانب الرئيسية لمعالجة الأخطاء في C# (.NET) بالتفصيل، بحيث لا يكون كودك موثوقًا فحسب، بل أيضًا قابلًا للقراءة.
1. البناء الأساسي: try و catch و finally
هذا هو الأساس الذي تبدأ به معرفة الاستثناءات. كتلة try تحتوي على الكود الذي قد يتسبب في خطأ. كتلة catch تلتقط الاستثناء وتعالجه. كتلة finally يتم تنفيذها دائمًا، بغض النظر عما إذا حدث خطأ أم لا - وهي مثالية لتحرير الموارد (إغلاق الملفات، الاتصالات).
الصيغة والمثال
using System;using System.IO;
class Program{ static void Main() { try { Console.Write("أدخل مسار الملف: "); string path = Console.ReadLine(); string content = File.ReadAllText(path); Console.WriteLine("محتوى الملف:"); Console.WriteLine(content); } catch (FileNotFoundException ex) { Console.WriteLine($"خطأ: الملف غير موجود. {ex.Message}"); } catch (UnauthorizedAccessException ex) { Console.WriteLine($"خطأ: لا يوجد إذن للوصول إلى الملف. {ex.Message}"); } catch (Exception ex) // التقاط عام لجميع الاستثناءات الأخرى { Console.WriteLine($"خطأ غير معروف: {ex.Message}"); } finally { Console.WriteLine("تم تنفيذ كتلة finally. نقوم بتحرير الموارد (إذا لزم الأمر)."); } }}نقاط مهمة:
- ترتيب كتل catch مهم: يجب أولاً التقاط الاستثناءات الأكثر تحديدًا (مثل
FileNotFoundException)، ثم الأكثر عمومية (Exception). إذا وضعت الكتلة العامة أولاً، فلن تصل أبدًا إلى الكتل الأكثر تحديدًا. - كتلة finally ليست إلزامية. إذا لم تكن بحاجة إلى تحرير الموارد بشكل مضمون، يمكنك حذفها.
- لا تلتقط
Exceptionبدون داع. إذا كنت لا تعرف كيفية معالجة الخطأ، فمن الأفضل السماح للبرنامج بالانهيار - سيساعد ذلك في اكتشاف المشكلة في مرحلة التطوير.
2. تحرير الموارد باستخدام using
على الرغم من أن finally أداة قوية، إلا أن كتابتها في كل مرة لأشياء مثل إغلاق الملفات أو الاتصالات بقاعدة البيانات أمر مرهق. بالنسبة للكائنات التي تطبق واجهة IDisposable، يوجد في C# عامل using. يضمن استدعاء طريقة Dispose() عند الخروج من الكتلة، حتى في حالة حدوث استثناء.
مقارنة بين الطريقتين
بدون using (تحرير يدوي):
StreamReader reader = null;try{ reader = new StreamReader("data.txt"); string line = reader.ReadLine(); // ... العمل مع reader}finally{ if (reader != null) reader.Dispose();}مع استخدام using:
using (StreamReader reader = new StreamReader("data.txt")){ string line = reader.ReadLine(); // ... العمل مع reader}// سيتم استدعاء Dispose() تلقائيًا