try-catch (مرجع #C)

تتكون عبارة try-catch من كتلة try متبوعة بكتلة واحدة أو أكثر من catch التي تحدد معالجات للاستثناءات المختلفة. عندما يتم طرح استثناء، يبحث وقت تشغيل اللغة العامة (CLR) عن عبارة catch التي تعالج هذا الاستثناء. إذا لم يتضمن الأسلوب الذي يتم تنفيذه حالياً كتلة catch يبحث CLR عن الأسلوب الذي قام باستدعاء الأسلوب الحالي وهكذا لأعلى في مكدس الاستدعاءات. إذا لم يتم العثور على كتلة catch فيعرض CLR رسالة استثناء غير معالج للمستخدم ويقوم بإيقاف تنفيذ البرنامج.

تحتوي كتلة try التعليمات البرمجية المحمية التي قد تؤدي إلى حدوث الاستثناء. يتم تنفيذ الكتلة حتى يتم إلقاء استثناء أو يتم تكملت الكتلة بنجاح. على سبيل المثال، المحاولة التالية لتحويل (cast) كائن null يطرح استثناء NullReferenceException ‏:

object o2 = null;
try
{
    int i2 = (int)o2;   // Error
}

على الرغم من أن جملة catch يمكن استخدامها بدون وسيطات لإلتقاط أي نوع من الاستثناءات، لا ننصح بطريقة الاستخدام هذه. بشكل عام، ينبغي عليك فقط التقاط الاستثناءات التي تعرف كيفية إصلاحها. ولذلك، يجب عليك دائمًا تحديد وسيطة كائن مشتقة من System.Exception على سبيل المثال:

catch (InvalidCastException e) 
{
}

يمكنك استخدام أكثر من جملة catch في نفس عبارة try-catch. في هذه الحالة، ترتيب عبارات catch مهم لأنه يتم فحص عبارات catch بالترتيب. قم بالتقاط الاستثناءات الأكثر تحديداً قبل تلك الأقل تحديداً. سيقوم المحول البرمجي بإنتاج خطأ إذا قمت بترتيب كتل catch الخاصة بك بحيث لا يمكن الوصول إلى الكتل الأخيرة أبداً.

يمكن استخدام عبارة throw في كتلة catch لإعادة طرح الاستثناء الذي تم التقاطه بواسطة عبارة catch. فعلى سبيل المثال:

catch (InvalidCastException e) 
{
    throw (e);    // Rethrowing exception e
}

يمكن أيضاً طرح استثناء جديد. عند القيام بذلك، حدد الاستثناء الذي قمت بالتقاطه بأن يكون الاستثناء الداخلي:

catch (InvalidCastException e) 
{
   // Can do cleanup work here.
    throw new CustomException("Error message here.", e);
}

إن كنت تريد إعادة طرح الاستثناء الذي يتم معالجته حالياً بواسطة جملة catch من غير معلمات قم باستخدام عبارة throw من غير وسيطات. فعلى سبيل المثال:

catch
{
    throw;
}

عندما تكون داخل كتلة try فقط قم بتهييء المتغيرات التي تم تعريفها هناك; وإلا، يمكن أن يحدث استثناء قبل إتمام تنفيذ الكتلة. على سبيل المثال، في مثال التعليمات البرمجية التالي، تم تهيئة المتغير x داخل كتلة try. أي محاولة لاستخدام هذا المتغير خارج كتلة try في عبارة Write(x) سينشئ خطأ في المحول البرمجي.

static void Main() 
{
    int x;
    try 
    {
        // Don't initialize this variable here.
        x = 123;
    }
    catch
    {
    }
    // Error: Use of unassigned local variable 'x'.
    Console.Write(x);
}

للحصول على مزيد من المعلومات حول catch، راجع try-catch-finally.

مثال

في هذا المثال، تحتوي كتلة try على استدعاء لأسلوب ProcessString وقد يتتسبب في حدوث استثناء. جملة catch تحتوي على معالج استثناء يعرض فقط رسالة على الشاشة. عند استدعاء عبارة throw من داخل MyMethod، يبحث النظام عن عبارة catch ويعرض الرسالة Exception caught.

    class TryFinallyTest
{
    static void ProcessString(string s)
    {
        if (s == null)
        {
            throw new ArgumentNullException();
        }
    }

    static void Main()
    {
        string s = null; // For demonstration purposes.

        try
        {            
            ProcessString(s);
        }

        catch (Exception e)
        {
            Console.WriteLine("{0} Exception caught.", e);
        }
    }
}
    /*
    Output:
    System.ArgumentNullException: Value cannot be null.
       at TryFinallyTest.Main() Exception caught.
     * */

في هذا المثال، يتم استخدام عباراتين catch. يتم التقاط الاستثناء الأكثر خصوصية والذي يأتي أولاً.

class ThrowTest3
{
    static void ProcessString(string s)
    {
        if (s == null)
        {
            throw new ArgumentNullException();
        }
    }

    static void Main()
    {
        try
        {
            string s = null;
            ProcessString(s);
        }
        // Most specific:
        catch (ArgumentNullException e)
        {
            Console.WriteLine("{0} First exception caught.", e);
        }
        // Least specific:
        catch (Exception e)
        {
            Console.WriteLine("{0} Second exception caught.", e);
        }
    }
}
/*
 Output:
System.ArgumentNullException: Value cannot be null.
   at TryFinallyTest.Main() First exception caught.
*/

في المثال السابق، إذا قمت بالبدء مع الاستثناء الأقل تحديداً، ستحصل على رسالة خطأ:

A previous catch clause already catches all exceptions of this or a super type ('System.Exception')

ومع ذلك، لالتقاط الاستثناء الأقل تحديداً, استبدل عبارة throw بالتالي:

throw new Exception();

مواصفات لغة #C

لمزيد من المعلومات، راجع مواصفات لغة #C. مواصفات اللغة هي المصدر النهائي لبناء جملة C# واستخدامها.

راجع أيضًا:

المهام

كيفية: استثناءات يرمي بشكل صريح

المرجع

الكلمات الأساسية لـ #C

The try, catch, and throw Statements

استثناء معالجة البيانات ( مرجع C# )

الإلقاء ( مرجع C# )

try-finally (مرجع #C)

المبادئ

دليل البرمجة لـ #C

موارد أخرى

مرجع C#‎