تمرين - إنشاء استثناء وطرحه

مكتمل

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

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

إنشاء مشروع تعليمة برمجية جديدة

الخطوة الأولى هي إنشاء مشروع تعليمة برمجية يمكنك استخدامه أثناء هذه الوحدة النمطية.

  1. افتح مثيلا جديدا من Visual Studio Code.

  2. في القائمة ملف ، حدد فتح مجلد.

  3. في مربع الحوار فتح مجلد ، انتقل إلى مجلد سطح مكتب Windows.

  4. في مربع الحوار فتح مجلد ، حدد مجلد جديد.

  5. قم بتسمية المجلد الجديد ThrowExceptions101، ثم حدد Select Folder.

  6. في القائمة المحطة الطرفية، حدد محطة طرفية جديدة.

    ستستخدم أمر .NET CLI لإنشاء تطبيق وحدة تحكم جديد.

  7. في موجه أوامر لوحة TERMINAL، أدخل الأمر التالي:

    dotnet new console
    
  8. أغلق لوحة TERMINAL.

مراجعة نموذج تطبيق

استخدم الخطوات التالية لتحميل نموذج التطبيق ومراجعته.

  1. افتح ملف Program.cs.

  2. في القائمة عرض، حدد لوحة الأوامر.

  3. في موجه الأوامر، أدخل .net: g ثم حدد .NET: Generate Assets for Build and Debug.

  4. استبدل محتويات ملف Program.cs بالتعليمات البرمجية التالية:

    // Prompt the user for the lower and upper bounds
    Console.Write("Enter the lower bound: ");
    int lowerBound = int.Parse(Console.ReadLine());
    
    Console.Write("Enter the upper bound: ");
    int upperBound = int.Parse(Console.ReadLine());
    
    decimal averageValue = 0;
    
    // Calculate the sum of the even numbers between the bounds
    averageValue = AverageOfEvenNumbers(lowerBound, upperBound);
    
    // Display the value returned by AverageOfEvenNumbers in the console
    Console.WriteLine($"The average of even numbers between {lowerBound} and {upperBound} is {averageValue}.");
    
    // Wait for user input
    Console.ReadLine();
    
    static decimal AverageOfEvenNumbers(int lowerBound, int upperBound)
    {
        int sum = 0;
        int count = 0;
        decimal average = 0;
    
        for (int i = lowerBound; i <= upperBound; i++)
        {
            if (i % 2 == 0)
            {
                sum += i;
                count++;
            }
        }
    
        average = (decimal)sum / count;
    
        return average;
    }
    
  5. خذ دقيقة لمراجعة التعليمات البرمجية.

    لاحظ أن التطبيق ينفذ المهام التالية:

    1. تستخدم Console.ReadLine() عبارات المستوى الأعلى عبارات للحصول على قيم ل lowerBound و upperBound.

    2. تمر lowerBound عبارات المستوى الأعلى و upperBound كوسيطات عند استدعاء AverageOfEvenNumbers الأسلوب .

    3. AverageOfEvenNumbers يقوم الأسلوب بتنفيذ المهام التالية:

      1. يعلن عن المتغيرات المحلية المستخدمة في العمليات الحسابية.
      2. يستخدم تكرار حلقي for لجمع الأرقام الزوجية بين lowerBound و upperBound. يتم تخزين المجموع في sum.
      3. حساب عدد الأرقام المضمنة في المجموع. يتم تخزين العدد في count.
      4. يخزن متوسط الأرقام التي تم جمعها في متغير يسمى average. يتم إرجاع قيمة average .
    4. تقوم عبارات المستوى الأعلى بطباعة القيمة التي تم إرجاعها إلى AverageOfEvenNumbers وحدة التحكم ثم إيقاف التنفيذ مؤقتا.

تكوين بيئة تتبع الأخطاء

يقرأ نموذج التطبيق إدخال المستخدم من وحدة التحكم. لا تدعم لوحة وحدة تحكم DEBUG قراءة الإدخال من وحدة التحكم. تحتاج إلى تحديث ملف launch.json قبل أن تتمكن من تشغيل هذا التطبيق في مصحح الأخطاء.

  1. استخدم طريقة عرض EXPLORER لفتح ملف launch.json.

  2. في ملف launch.json، قم بتحديث السمة console كما يلي:

    // For more information about the 'console' field, see https://aka.ms/VSCode-CS-LaunchJson-Console
    "console":"integratedTerminal",
    

    القيمة الافتراضية للسمة console هي internalConsole، والتي تتوافق مع لوحة وحدة تحكم DEBUG. لسوء الحظ، لا تدعم لوحة وحدة تحكم DEBUG إدخال وحدة التحكم. يتوافق integratedTerminal الإعداد مع لوحة TERMINAL، التي تدعم إدخال وحدة التحكم والإخراج.

  3. احفظ التغييرات التي أجريتها على ملف launch.json، ثم أغلق الملف.

  4. في قائمة Visual Studio Code Run ، حدد Start Debugging.

  5. قم بالتبديل إلى لوحة TERMINAL.

  6. في موجه "الحد الأدنى"، أدخل 3

  7. في المطالبة "الحد الأعلى"، أدخل 11

  8. لاحظ أن التطبيق يعرض الرسالة التالية ثم يتوقف مؤقتا:

    The average of even numbers between 3 and 11 is 7.
    
  9. للخروج من التطبيق، اضغط على مفتاح الإدخال Enter.

طرح استثناء في الأسلوب AverageOfEvenNumbers

AverageOfEvenNumbers يتوقع الأسلوب حد أعلى أكبر من الحد السفلي. DivideByZero يحدث خطأ إذا كان الحد السفلي أكبر من الحد الأعلى أو مساويا له.

تحتاج إلى تحديث AverageOfEvenNumbers الأسلوب لطرح استثناء عندما يكون الحد السفلي أكبر من الحد الأعلى أو مساويا له.

  1. خذ دقيقة للنظر في الطريقة التي تريد بها معالجة المشكلة.

    أحد الخيارات هو التفاف حساب average داخل كتلة التعليمات البرمجية trycatch والاستثناء DivideByZero عند حدوثه. يمكنك إعادة وضع الاستثناء ثم معالجته في التعليمات البرمجية للاتصال.

    خيار آخر هو تقييم معلمات الإدخال قبل بدء العمليات الحسابية. إذا كان lowerBound أكبر من أو يساوي upperBound، يمكنك طرح استثناء.

    تقييم المعلمات وطرح استثناء قبل بدء العمليات الحسابية هو الخيار الأفضل.

  2. ضع في اعتبارك نوع الاستثناء الذي يجب طرحه.

    هناك نوعان من الاستثناءات التي تتوافق مع المشكلة:

    • ArgumentOutOfRangeException ArgumentOutOfRangeException- يجب طرح نوع استثناء فقط عندما تكون قيمة الوسيطة خارج نطاق القيم المسموح به كما هو محدد بواسطة الأسلوب الذي تم استدعاؤه. على الرغم من عدم AverageOfEvenNumbers تحديد نطاق مسموح به بشكل صريح ل lowerBound أو upperBound، فإن قيمة lowerBound تعني النطاق المسموح به ل upperBound.
    • InvalidOperationException InvalidOperationException: يجب طرح نوع استثناء فقط عندما لا تدعم شروط تشغيل الأسلوب الإكمال الناجح لاستدعاء أسلوب معين. في هذه الحالة، يتم تأسيس شروط التشغيل بواسطة معلمات الإدخال للأسلوب.

    عندما يكون لديك نوعان أو أكثر من أنواع الاستثناءات للاختيار من بينها، حدد نوع الاستثناء الذي يناسب المشكلة بشكل أوثق. في هذه الحالة، يتم محاذاة نوعي الاستثناء إلى المشكلة بالتساوي.

    عندما يكون لديك نوعان أو أكثر من أنواع الاستثناءات التي تتم محاذاتها مع المشكلة بشكل متساو، حدد نوع الاستثناء الأكثر ضيق النطاق. ArgumentOutOfRangeException يتم تحديد نطاق نوع الاستثناء إلى الوسيطات التي تم تمريرها إلى الأسلوب . InvalidOperationException يتم تحديد نطاق نوع الاستثناء لشروط تشغيل الأسلوب. في هذه الحالة، يكون نوع الاستثناء ArgumentOutOfRangeException أكثر تضييقا من نوع الاستثناء InvalidOperationException .

    AverageOfEvenNumbers يجب أن يطرح ArgumentOutOfRangeException الأسلوب استثناء.

  3. في الجزء العلوي من AverageOfEvenNumbers الأسلوب، للكشف عن مشكلة الحد الأعلى، قم بتحديث التعليمات البرمجية الخاصة بك كما يلي:

    if (lowerBound >= upperBound)
    {
    
    }
    
    int sum = 0;    
    
  4. لإنشاء استثناء وطرحه ArgumentOutOfRangeException ، قم بتحديث كتلة التعليمات البرمجية if كما يلي:

    if (lowerBound >= upperBound)
    {
        throw new ArgumentOutOfRangeException("upperBound", "ArgumentOutOfRangeException: upper bound must be greater than lower bound.");
    }
    

    يقوم سطر التعليمات البرمجية هذا بتهيئة مثيل جديد للفئة ArgumentOutOfRangeException باسم معلمة الإدخال التي تتسبب في الاستثناء ورسالة خطأ محددة.

التقاط الاستثناء في التعليمة البرمجية للاتصال

كلما أمكن، يجب اكتشاف الاستثناءات على مستوى مكدس الاستدعاءات حيث يمكن معالجتها. في نموذج التطبيق هذا، يمكن إدارة معلمات AverageOfEvenNumbers الأسلوب في أسلوب الاستدعاء (عبارات المستوى الأعلى).

  1. مرر لأعلى إلى عبارات المستوى الأعلى.

  2. لإحاطة AverageOfEvenNumbers استدعاء الأسلوب وعقبة Console.WriteLine داخل كتلة التعليمات البرمجية try ، قم بتحديث التعليمات البرمجية الخاصة بك كما يلي:

    try
    {
        // Calculate the sum of the even numbers between the bounds
        averageValue = AverageOfEvenNumbers(lowerBound, upperBound);
    
        // Display the result to the user
        Console.WriteLine($"The average of even numbers between {lowerBound} and {upperBound} is {averageValue}.");
    }
    
  3. لإنشاء العبارة المقترنة catch ، أدخل التعليمات البرمجية التالية:

    catch(ArgumentOutOfRangeException ex)
    {
    
    }
    
  4. خذ دقيقة للنظر في كيفية التعامل مع الاستثناء.

    لمعالجة هذا الاستثناء، يجب أن تقوم التعليمات البرمجية بما يلي:

    • شرح المشكلة للمستخدم.
    • الحصول على قيمة جديدة ل upperBound.
    • اتصل AverageOfEvenNumbers باستخدام الجديد upperBound.
    • تابع إلى catch الاستثناء إذا كان الجديد upperBound المقدم لا يزال أقل من أو يساوي lowerBound.

    يتطلب المتابعة إلى catch الاستثناء تكرارا حلقيا. نظرا لأنك تريد استدعاء AverageOfEvenNumbers الأسلوب مرة واحدة على الأقل، do يجب استخدام حلقة.

  5. لتضمين try كتل و catch داخل do حلقة، قم بتحديث التعليمات البرمجية الخاصة بك كما يلي:

    do
    {
        try
        {
            // Calculate the sum of the even numbers between the bounds
            averageValue = AverageOfEvenNumbers(lowerBound, upperBound);
    
            // Display the result to the user
            Console.WriteLine($"The average of even numbers between {lowerBound} and {upperBound} is {averageValue}.");
        }
        catch (ArgumentOutOfRangeException ex)
        {
    
        }
    }
    

    while التعبير مطلوب لتعريف شرط الخروج من التكرار do الحلقي. من الصعب تحديد الشرط قبل تعريف محتويات كتلة التعليمات البرمجية do . سيساعدك إكمال كتلة التعليمات catch البرمجية على while تحديد التعبير المطلوب.

  6. لشرح المشكلة للمستخدم والحصول على جديد upperBound، قم بتحديث كتلة التعليمات البرمجية الخاصة بك catch كما يلي:

    catch (ArgumentOutOfRangeException ex)
    {
        Console.WriteLine("An error has occurred.");
        Console.WriteLine(ex.Message);
        Console.WriteLine($"The upper bound must be greater than {lowerBound}");
        Console.Write($"Enter a new upper bound: ");
        upperBound = int.Parse(Console.ReadLine());
    }
    

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

  7. لتزويد المستخدم بخيار للخروج من الحلقة بدلا من إدخال حد أعلى جديد، قم بتحديث كتلة التعليمات البرمجية الخاصة بك catch كما يلي:

    catch (ArgumentOutOfRangeException ex)
    {
        Console.WriteLine("An error has occurred.");
        Console.WriteLine(ex.Message);
        Console.WriteLine($"The upper bound must be greater than {lowerBound}");
        Console.Write($"Enter a new upper bound (or enter Exit to quit): ");
        string? userResponse = Console.ReadLine();
        if (userResponse.ToLower().Contains("exit"))
        {
    
        }
        else
        {
            upperBound = int.Parse(userResponse);
        }
    }
    

    تتضمن كتلة التعليمات البرمجية المحدثة catch مسارين، مسار "إنهاء" ومسار "حد أعلى جديد".

  8. خذ دقيقة للنظر في while التعبير المطلوب للحلقة do .

    إذا أدخل المستخدم "Exit" عند المطالبة، يجب أن تخرج التعليمات البرمجية من التكرار الحلقي. إذا أدخل المستخدم حد أعلى جديدا، يجب أن تستمر الحلقة. while يمكن استخدام تعبير يقيم قيمة منطقية. على سبيل المثال:

    while (exit == false);
    

    سينشئ التعبير المقترح while السلوك التالي:

    • سيستمر التكرار do الحلقي في التكرار طالما أن القيمة المنطقية exit تساوي false.
    • ستتوقف الحلقة do عن التكرار بمجرد أن تكون القيمة المنطقية exit مساوية ل true.
  9. لإنشاء مثيل لمتغير منطقي يسمى exit، واستخدام exit لتعيين شرط الخروج من التكرار do الحلقي، قم بتحديث التعليمات البرمجية الخاصة بك كما يلي:

    bool exit = false;
    
    do
    {
        try
        {
            // Calculate the sum of the even numbers between the bounds
            averageValue = AverageOfEvenNumbers(lowerBound, upperBound);
    
            // Display the result to the user
            Console.WriteLine($"The average of even numbers between {lowerBound} and {upperBound} is {averageValue}.");
    
            exit = true;
        }
        catch (ArgumentOutOfRangeException ex)
        {
            Console.WriteLine("An error has occurred.");
            Console.WriteLine(ex.Message);
            Console.WriteLine($"The upper bound must be greater than {lowerBound}");
            Console.Write($"Enter a new upper bound (or enter Exit to quit): ");
            string? userResponse = Console.ReadLine();
            if (userResponse.ToLower().Contains("exit"))
            {
                exit = true;
            }
            else
            {
                exit = false;
                upperBound = int.Parse(userResponse);
            }
        }    
    } while (exit == false);
    
  10. احفظ التعليمات البرمجية المحدثة.

  11. في قائمة Run ، حدد Start Debugging.

  12. قم بالتبديل إلى لوحة TERMINAL.

  13. في موجه "الحد الأدنى"، أدخل 3

  14. في المطالبة "الحد الأعلى"، أدخل 3

  15. لاحظ أنه يتم عرض الإخراج التالي في لوحة TERMINAL:

    Enter the lower bound: 3
    Enter the upper bound: 3
    An error has occurred.
    ArgumentOutOfRangeException: upper bound must be greater than lower bound. (Parameter 'upperBound')
    The upper bound must be greater than 3
    Enter a new upper bound (or enter Exit to quit):
    
  16. في المطالبة بخط أعلى جديد، أدخل 11

  17. لاحظ أنه يتم عرض الإخراج التالي في لوحة TERMINAL:

    Enter the lower bound: 3
    Enter the upper bound: 3
    An error has occurred.
    ArgumentOutOfRangeException: upper bound must be greater than lower bound. (Parameter 'upperBound')
    The upper bound must be greater than 3
    Enter a new upper bound (or enter Exit to quit): 11
    The average of even numbers between 3 and 11 is 7.
    
  18. للخروج من التطبيق، اضغط على مفتاح الإدخال Enter.

تهانينا! لقد نجحت في طرح استثناء والقبض عليه والتعامل معه.

خلاصة

فيما يلي بعض الأشياء المهمة التي يجب تذكرها من هذه الوحدة:

  • تأكد من تكوين بيئة تتبع الأخطاء الخاصة بك لدعم متطلبات التطبيق الخاص بك.
  • يجب أن تطرح التعليمات البرمجية للأسلوب استثناء عند اكتشاف مشكلة أو شرط.
  • يجب اكتشاف الاستثناءات على مستوى في مكدس الاستدعاءات حيث يمكن حلها.