معالجة الاستثناءات Exceptions Handling
ما هي الاستثناءات في البرمجة....؟! وماهو مفهوم معالجة الاستثناءات (Exceptions Handling ) ....؟! وما طريقة معالجة الاستثناءات (Exceptions Handling ) في لغة C# ...؟؟! كيف يتم استخدام (try-catch ) في معالجة الاستثناءات (Exceptions Handling) .!! وكيف يمكن معالجة الاستثناءات (Exceptions Handling) باستخدام throw..!!!
معالجة الاستثناءات Exceptions Handling هي جزء أساسي من عملية تطوير البرمجيات، حيث تواجه البرامج بيئات متغيرة ومواقف غير متوقعة يمكن أن تؤدي إلى حدوث أخطاء. وفي لغة C# ، تتوفر العديد من الأدوات والميزات للتعامل مع الاستثناءات ومعالجتها بطريقة فعالة وهي الأسلوب الموصى به للتعامل مع الأخطاء. هذا المقال على كيف تتم معالجة الاستثناءات Exceptions Handling في C# . لنبدأ…
في هذا المقال سنتعرف:
- الأخطاء في البرمجة.
- معالجة الاستثناءات Exceptions Handling في لغة C# .
- استخدام Exception Class في معالجة الاستثناءات.
- أنواع الاستثناءات Exceptions في C# .
- استخدام "finally" Block مع الاستثناءات.
- معالجة الاستثناءات بواسطة "throw".
الأخطاء في البرمجة
في الحياة العملية يمكن أن تحدث أخطأ فعدم وجود أخطأ دليل على عدم القيام بشيء فالأشياء السيئة تحدث أحيانًا. في عالم الكمبيوتر من الممكن أن تسبب الأخطاء بتتلف الأقراص الصلبة، أوقد يتسبب عمل التطبيقات الأخرى على نفس الكمبيوتر الى أن تستنفد الذاكرة المتاحة أو قد تختفي اتصالات الشبكة اللاسلكية في أكثر اللحظات حرجًا.
كما أننا لايمكن أن نتنبأ بالأضرار التي تنتج عن الظواهر الطبيعية مثل صاعقة قريبة يمكن أن يكون لها تأثير إذا تسببت في انقطاع التيار الكهربائي أو فشل الشبكة بالطبع مثل هذه الحوادث تؤثر على عمل الكمبيوتر وبالتالي البرمجة .
وممكن أن يتسبب التصرف بطرق غير متوقعة من مستخدمين التطبيقات بحدوث الأخطاء في أي مرحلة عند تشغيل البرنامج ، وقد لا تكون العديد من الأخطاء في الواقع هي خطأ في التطبيق، بل حالة استثنائية لم تيم تعريفها في التطبيق فكيف يكتشفها ويتعامل معها؟
مما سبق يتضح لنا أنه من الوارد حدوث مشاكل وجود أخطاء تؤثر على تشغيل البرامج ، وبعض هذه المشاكل ممكن التعامل معه من خلال البرمجة. فإذا أردنا كتابة برامج قوية ، فنحن بحاجة إلى معرفة الاستثناءات Exceptions في البرمجة.
و الاستثناءات Exceptions في البرمجة هي الحالات الاستثنائية التي قد تعطل عمل الكود في الحالة الاعتيادية أو الأخطاء البرمجية التي ممكن أن تظهر أثناء التشغيل.
وتتم معالجة الاستثناءات Exceptions في البرمجة قبل أن تحدث ، وهذا بتوقع الشائع منها. في بداية الحديث عن الاستثناءات في البرمجة سنتعرف على أنواع الأخطاء البرمجية حيث تعدد أشكال الأخطاء التي قد تنتج أثناء عملية البرمجة ومنها:
- الـ Compiler Errors أو Syntax Errors وهي الأخطاء التي تحدث أثناء كتابة الكود، وهي أخطاء يمكن اكتشافها بسهولة بواسطة الـ Compiler الذي يتعرّف عليها ويعطي وصفًا عنها، وقد يزوّدنا أيضًا ببعض المقترحات لمعالجتها.
- الـ Logical Errors وتحدث عند وجود خطأ في الخوارزمية أو تطبيقها أوأنها لم تترجم الى الكود بشكل صحيح وهنا سوف يعمل البرنامج ولكن سوف يعطي نتائج غير صحيحة أو غيرمتوقعة للغرض المراد من البرنامج .
- الـ Runtime Errors والتي تحدث عند تشغيل البرنامج وتؤدي إلى توقف التنفيذ و توجد الكثير من الأسباب لحدوث مثل هذه الأخطاء. مثلاً القسمة على صفر إلى القراءة من ملف غير موجود عند حدوث مثل هذه الأخطاء نستخدم الإستثناءات لمعالجتها حيث أن لكل خطأ استثناءً Exception .يحتوي على معلومات بخصوص الخطأ الذي حدث.
هذه الأخطاء المعروفة في البرمجة و لمعالجة بعض من هذه الأخطاء توفر أغلب لغات البرمجة ومنها لغة سي شارب مايعرف بمعالجة الاستثناءات Exceptions Handling.
معالجة الاستثناءات Exceptions Handling في لغة C#
يمكن تعريف الاستثناء Exception بأنه المشكلة التي تنشأ أثناء تنفيذ البرنامج فهو استجابة لظروف استثنائية تنشأ أثناء تشغيل البرامج . و معالجة الاستثناءات (Exceptions Handling) هي طريقة لنقل التنفيذ من جزء البرنامج المتضرر إلى آخر يعمل أو ينهي التنفيذ بطريقة صحيحة وآمنه.
و لكتابة برامج تدرك الاستثناءات Exceptions في لغة C# ، نستخدم try...catch Blocks هذه الطريقة في معالجة الاستثناءات (Exceptions Handling) توفرها أغلب لغات البرمجة إن لم تكن كلها و C# من اللغات التي توفرها لنرى الآن طريقة تنفيذها من خلال تعليمات C# .
لمعالجة الاستثناءات Exceptions Handling توفر C# حلاً في شكل Blocks وهي try و catch باستخدام هذه الـ Blocks ، يتم فصل عبارات البرنامج الأساسية عن عبارات معالجة الأخطاء. ففي try" Block" يتم تنفيذ الجزء المتوقع ظهور الخطأ فيه وفي حال تعذر التنفيذ سيوقف تنفيذ وينتقل إلى تنفيذ catch" Block" . وهذه باستخدام الكلمات المحجوزة try و catch.
try" Block"
نعلن عن try" Block" بواسطة الكلمة المحجوزة try و داخل try" Block" نكتب الكود المتوقع حدوث خطأ به وعندما يتم تشغيل الكود ، فإنه يحاول تنفيذ جميع العبارات الموجودة في try" Block" ، وإذا لم يولد أي من العبارات استثناءً ، فسيتم تشغيلها جميعًا، واحدة تلو الأخرى ، حتى الاكتمال. أما في حالة حدوث حالة استثناء ، يقفز التنفيذ خارج الـ try" Block" إلى جزء آخر من التعليمات البرمجية المصممة لإلتقاط ومعالجة الاستثناء - معالج التقاط catch" Block" .
معالج الإلتقاط catch" Block"
بواسطة الكلمة المحجوزة catch يتم الإعلان عن معالج الالتقاط catch" Block" مباشرة بعد try" Block" للتعامل مع أي حالات خطأ محتملة.
يهدف معالج الإلتقاط catch إلى التقاط نوع معين من الاستثناءات ومعالجتة معه، ويمكن أن يكون لدينا أكثر من معالج التقاط catch" Block" بعد try" Block" ، كل من معالجات الإلتقاط هذه مخصصة لإستكشاف استثناء معين ومعالجته.
أي يمكّننا توفير معالجات أخطاء مختلفة قد تظهر فى try" Block" و إذا تسببت أي من العبارات داخل try" Block" فى حدوث خطأ أو حالة استثناء، فإن التنفيذ ينتقل الى المعالج الالتقاط المناسب لمعالجة الخطأ. حيث يتم فحص معالجات الالتقاط بعد try" Block" والانتقال بالتنفيذ مباشرة إلى أول معالج مطابق.
و الصيغة العامة لتعريف معالجة الاستثناءات Exceptions Handling هي :
try { //Type the code instructions here } catch { //Catch code with error message here }
وهنا مثال يوضح طريقة معالجة الاستثناءات Exceptions Handling في لغة سي شارب مثال:
int [] i = new int[3];
try
{
Console.WriteLine("In try block...");
i[0] = 0;
i[1] = 4/i[0];
Console.WriteLine("The second element of array is: "+ i[1]);
}
catch
{
Console.WriteLine("In catch block...");
Console.WriteLine("Exception Caught");
}
لتكـن النتيجـة
In try block... In catch block... Exception Caught
في هذا المثال السابق تم افتعال خطأ القسمة على صفر لهذا نرى الـ Compiler عندما واجهه الخطأ تجاوز التنفيذ فى try" Block" الى catch" Block" . ولكن ماذا لو لم نعلم اين الخطأ في كود الـ try" Block" هنا لابد ان معالج الالتقاط يوفر رسالة خطأ تنبه بنوع الخطأ الذي حدث. وفي مثل هذه الحالة نستخدم الـ Exception Class.
استخدام Exception Class في معالجة الاستثناءات
توفر لغة سي شارب Exception Class الـ Class الذي يحتوي على مجموعة من الـ Classes التي تستخدم في معالجة حالات الاستثناءات المتوقعة والأكثر سيوعاً فبدلاً من انشاء اكثر من معالج التقاط catch للأخطاء المتوقعة. ننشيء معالج التقاط واحد و نقوم بعمل Object من Exception Class ليستخدم في catch" Block" ويطبع رسالة بنوع الخطأ الذي حدث لاحظ/ ي طريقة العمل في المثال التالي:
int [] i = new int[3];
try
{
Console.WriteLine("In try block...");
i[0] = 0;
i[1] = 4/i[0];
Console.WriteLine("The second element of array is: "+ i[1]);
}
catch( Exception e)
{
Console.WriteLine("In catch block...");
Console.WriteLine("Exception Caught");
Console.WriteLine(e.Message);
}
لتكـن النتيجـة
In try block... In catch block... Exception Caught Attempted to divide by zero.
أنواع الاستثناءات Exceptions في C #
مما سبق رأينا طريقة معالجة الاستثناءات Exceptions Handling في C # بواسطة الـ Exception Classes حيث يتم اشتقاق الـ Exception classes بشكل مباشر أو غير مباشر System.Exception Class.
وتتوفر في لغة سي شارب بعض الـ Exception classes المشتقة من System.Exception Class التي تختص بمعالجة استثناءات من نوع معين ومنها :
- System.ApplicationException Class وتعالج الاستثناءات الخاصة بالتطبيقات وتحدد بواسطة المبرمجون.
- System.SystemException Class وتعالج كافة استثناءات النظام المعرفة مسبقًا.
العمل مع هذه الـ classes يجعل الامر اكثر تحديداً مع توقع الاستثناء المحتمل وانشاء رسالة بحسب نوع هذا الاستثناء في ويوضح الشكل التالي بعض الأمثلة للـ Classes المشتقة من Exception Class :
ويوضح المثال التالي طريقة العمل مع الاستثناء المتوقع في لغة سي شارب :
int [] i = new int[3];
try
{
Console.WriteLine("In try block...");
i[0] = 0;
i[1] = 4/i[0];
Console.WriteLine("The second element of array is: "+ i[1]);
}
catch( DivideByZeroException e)
{
Console.WriteLine("In catch block...");
Console.WriteLine("Exception Caught");
Console.WriteLine(e.Message);
}
ويمكن العمل مع عدد من catch" Block" وتوقع عدد من الاستثناءات المحتملة من خلال العمل مع عدد من catch" block" لنرى المثال التالي:
string s = "Programming"; // set null value for NullReferenceException
int [] i = new int[3];
try
{
Console.WriteLine("Entering try block...");
Console.WriteLine("Lower cause name is: "+ s.ToLower());
//can cause IndexOutOfRangeException by => i[6].ToString()
Console.WriteLine("First element of array is: "+ i[6].ToString());
Console.WriteLine("Leaving the try block..");
}
//catch for NullReferenceExeptio
catch(NullReferenceException e)
{
Console.WriteLine("In catch block...");
Console.WriteLine(e.Message);
}
//catch for IndexOutOfRangeException
catch(IndexOutOfRangeException e)
{
Console.WriteLine("In catch block...");
Console.WriteLine(e.Message);
}
// the catch for any other exceptions
catch(Exception e)
{
Console.WriteLine("In catch block...");
Console.WriteLine("Exception Caught");
Console.WriteLine(e.Message);
}
استخدام finally" Block" مع الاستثناءات
الـ finally" Block" هو Block يعمل مع try…catch" Blocks" والـ finally" Block" اختاري و يرتبط بالعمل معها حيث يتم تنفيذ تعليماته في كل الأحوال ويستخدم للتحقق من قراءة البرنامج للـ try…catch" Blocks" حيث ان تم تجاوز الاكواد في كلاهما لا يتم يتجاوز الـ finally" Block". ويوضح المثال التالي طريقة استخدام الـ finally" Block" في معالجة الاستثناءات (Exceptions Handling) :
string s = null;
try
{
Console.WriteLine("Entering try block...");
Console.WriteLine("Leaving the try block..");
}
//catch for NullReferenceExeptio
catch(NullReferenceException e)
{
Console.WriteLine("In catch block...");
Console.WriteLine(e.Message);
}
finally
{
Console.WriteLine("In finally block...");
}
معالجة الاستثناءات بواسطة "throw"
في لغة سي شارب يمكن أيضاً معالجة الاستثناءات بواسطة الكلمة المحجوزة "throw" . و تفيد throw بالإبلاغ عن المشكلة في حال حدوثها وإعطاء رسالة الخطأ المناسبة و تمكننا throw من عمل Object للـ Exception. ويوضح المثال التالي على طريقة معالجة الاستثناءات (Exceptions Handling) بواسطة throw :
int X = 0;
if ( X ==0 )
throw new DivideByZeroException ("Invalid Division");
Console.WriteLine(10/X);
لتكـن النتيجـة
Unhandled exception. System.DivideByZeroException: Invalid Division
هنا تم استخدام throw لعمل Object من DivideByZeroException برسالة الخطأ التي أرسلنها "Invalid Division" في هذه الحالة سيتم حفظ التتبع للاستثناء الأصلي في مكدس الاستدعاءات stack trace.
وبما أنه لا يوجد لدينا catch" Block" للالتقاط الاستثناء ومعالجته فإنه يتعطل ولكي لا يتم الاحتفاظ بتتبع الاستثناء الأصلي في Stack Trace يمكننا إجراء بعض العمليات ، عند اكتشاف الاستثناء يتم تسجيل الخطأ ، ثم إعادة طرح الاستثناء.
إعادة طرح استثناء يعني استدعاء تعليمة throw بدون Parameters الاستدعاء هنا لابد ان يكون داخل catch" Block" وهذا الإجراء لا يمكن فعله إلا داخل catch" Block" وتتضح طريقة العمل لإعادة طرح الاستثناء :
int X = 0;
try
{
if ( X ==0 )
Console.WriteLine(10/X);
}
catch(DivideByZeroException e)
{
Console.WriteLine(e.Message);
throw;
}
أمثلة هذا المقال متوفرة بالكامل هنا.
تعد معالجة الاستثناءات Exceptions Handling في C# جزءًا أساسيًا من إدارة الأخطاء والحفاظ على استقرار البرامج. عند تطوير تطبيقات C# ، يجب أن نفكر في الأمور غير المتوقعة التي يمكن أن تحدث ونعالجها بشكل صحيح بواسطة معالجة الاستثناءات Exceptions Handling . هذا يساعدنا على تحسين قدرة التطبيق على التعامل مع الأخطاء وتوفير تجربة مستخدم أفضل.
إلى هنا ينتهي هذا المقال الذي تعرفنا فيه على أنواع الأخطاء في البرمجة ومفهوم معالجة الاستثناءات Exceptions Handling في البرمجة و طريقة معالجة الاستثناءات Exceptions Handling من خلال تعليمات لغة C#.