خواص Exception

کلاس پايه System.Exception کلاسي است که ساير کلاسهاي استثناء از آن ارث بري می‌کنند. بنابراين خواص اين کلاس در دسترس ساير کلاسهاي استثناء می‌باشد. در جدول زير برخي از خواص برجسته کلاس Exception که در همه کلاسهاي استثناء وجود دارند آمده است :

خواص توضيحات
InnerException استثنايي که موجب توليد مشکل شده است
Message متني که استثناء را شرح می‌دهد
StackTrace براي تشخيص خطايي که باعث ايجاد مشکل شده است

خاصيت Message

اين خاصيت به شما اجازه می‌دهد که در مورد استثناء به وجود آمده توضيحاتي ارائه دهيد. به عنوان مثال به کد زير توجه کنيد :

int x = 1;
int y = 0;
int z;

try
{
    z = x / y;
}
catch (Exception ex)
{
    Console.WriteLine(ex.Message);
}
Attempted to divide by zero.

در مثال بالا عمداً يک عدد را بر صفر تقسيم می‌کنیم تا بلوک catch اجرا شود. به اين نکته توجه کنيد که چون يک نمونه از کلاس Exception ايجاد کرده‌ایم بنابراين می‌توانیم از خاصيت Message استفاده کنيم. سپس محتويات خاصيت Message را به وسيله متد ()Console.WriteLine چاپ می‌کنیم. حال اگر برنامه را اجرا کنيم پيغام خطا نمايش داده می‌شود. همه کلاسهاي استثناء از قبل تعريف شده در دات نت پيغام خطاهاي مرتبط با خودشان را در خاصيت property دارند. اگر يک استثناء ايجاد کنيد می‌توانید از سربارگذاري سازنده کلاس Exception که يک رشته که همان پيغام خطاست را دريافت می‌کند، استفاده کنيد

try
{
    if (y == 0)
    {
        throw new DivideByZeroException("You cannot divide by zero. Sorry my friend.");
    }
    else
    {
        z = x / y;
    }
}
catch (Exception e)
{
    Console.WriteLine(e.Message);
}
You cannot divide by zero. Sorry my friend.

خاصيت InnerException

از اين خاصيت براي تشخيص خطايي که باعث ايجاد مشکل شده است استفاده می‌شود. به عنوان مثال فرض کنيد که يک برنامه نويس می‌خواهد تشخيص دهد که آيا شماره حسابي که توسط کاربر وارد شده است صحيح می‌باشد يا نه؟ اولين کاري که بايد انجام شود تبديل نوع رشته به عدد صحيح است. اگر عدد وارد شده توسط کاربر که از نوع رشته است را نتوانيم به درستي به نوع عدد تبديل کنيم خطاي FormatException رخ می‌دهد. در قسمت chatch براي FormatException، می‌توان مانور بيشتري داد و استثناء رو مديريت کرد و پيغام مناسب را به کاربر نشان داد. به کد زير توجه کنيد :

   1: using System;
   2: 
   3: namespace InnerExceptionDemo
   4: {
   5:     class Program
   6:     {
   7:         static int ProcessAccountNumber(string accountNumber)
   8:         {
   9:             try
  10:             {
  11:                 return Convert.ToInt32(accountNumber);
  12:             }
  13:             catch (FormatException formatException)
  14:             {
  15:                 throw new Exception("Invalid Account Number.", formatException);
  16:             }
  17:         }
  18:         static void Main(string[] args)
  19:         {
  20:             Console.Write("Enter an account number: ");
  21:             string input = Console.ReadLine();
  22: 
  23:             try
  24:             {
  25:                 int accountNumber = ProcessAccountNumber(input);
  26:             }
  27:             catch (Exception ex)
  28:             {
  29:                 Console.WriteLine("Current exception's message: {0}", ex.Message);
  30:                 Console.WriteLine("Inner exception's message: {0}", 
  31:                                         ex.InnerException.Message);
  32:             }
  33:         }
  34:     }
  35: }
Enter an account number: abcde
Current exception's message: Invalid Account Number.
Inner exception's message: Input string was not in a correct format.

در خطوط 17-7 يک متد به نام ProcessAccountNumber تعريف کرده‌ایم. اين متد يک آرگومان از نوع رشته قبول می‌کند که همان رشته‌ای است که توسط کاربر وارد می‌شود. همانطور که در خط 25 مشاهده می‌کنید متد (ProcessAccountNumber) فراخواني شده و رشته وارد شده توسط کاربر به عنوان آرگومان به آن ارسال می‌شود. اين خط کد (خط 25) در داخل يک بلوک try قرار داده می‌شود چون ممکن است باعث ايجاد خطا شود. بعد از اينکه متد فراخواني شد برنامه به محل تعريف متد منتقل می‌شود (خط 7). در داخل متد دستور try…catch ديگري وجود دارد. در داخل بلوک try سعي می‌کنیم که رشته را به عدد تبديل کرده و مقدار آن را برگشت دهيم. اگر رشته نتواند به عدد تبديل شود خطاي FormatException رخ داده م در نتيجه بلوک catch اجرا می‌شود.
در داخل بلوک catch يک نمونه از کلاس Exception ايجاد کرده و پيغام دلخواه به عنوان اولين پارامتر ورودي و FormatException را به عنوان پارامتر دوم که نشان دهنده يک InnerException است را براي آن مشخص می‌کنیم. بعد از اجراي اين قسمت بلاک catch تابع اصلي يعني خط 27 اجرا خواهد شد. در اين بلاک اول Exception جديد و خاصيت Message آن نمايش داده می‌شود و بعد از آن خاصيت Message استثناء اي که باعث اجراي اين بلاک شد است به عنوان InnerException نمايش داده می‌شود.

خاصيت StackTrace

خاصيت StackTrace در کلاس System.Exception به شما اجازه می‌دهد تا بفهميد در کدام متد از متدهای پشته خطا رخ داده است. اين خاصيت براي زماني است که شما متد 1 را داخل متد 2 صدا زده‌اید و متد 1 داراي خطا است. با استفاده از اين خاصيت می‌توانید بفميد که در متد 1 و به دنبال آن در متد 2 هم خطا رخ داده است. به کد زير دقت کنيد:

   1: using System;
   2: 
   3: namespace StackTraceDemo
   4: {
   5:     class Program
   6:     {
   7:         static void Method1()
   8:         {
   9:             Method2();
  10:         }
  11: 
  12:         static void Method2()
  13:         {
  14:             Method3();
  15:         }
  16: 
  17:         static void Method3()
  18:         {
  19:             throw new Exception("Exception at Method3()");
  20:         }
  21: 
  22:         static void Main(string[] args)
  23:         {
  24:             try
  25:             {
  26:                 Method1();
  27:             }
  28:             catch (Exception ex)
  29:             {
  30:                 Console.WriteLine(ex.StackTrace);
  31:                 Console.ReadKey();
  32:             }
  33:         }
  34:     }
  35: }
at StackTraceDemo.Program.Method3() in C:StackTraceDemoProgram.cs:line 19
at StackTraceDemo.Program.Method2() in C:StackTraceDemoProgram.cs:line 14
at StackTraceDemo.Program.Method1() in C:StackTraceDemoProgram.cs:line 9
at StackTraceDemo.Program.Main(String[] args) in C:StackTraceDemoProgram.cs:line 26

هر خط 3 فايل و متد و خطِ داراي خطا را نشان می‌دهد. متد 3 به عنوان منبع خطا در اولين خط نشان داده شده است.