اینجا میتونی برنامه نویسی ویندوز رو به طور کاملا رایگان یاد بگیری
3 سال پیش / خواندن دقیقه

مدیریت Exception ها در سی شارپ

در فصل قبل مشاهده کردید که در زمان اجرای برنامه ممکن است خطاهایی رخ دهند. این خطا ها به صورت استثنا در برنامه رخ میدهد. در سی شارپ ار دستوراتی برای مدیریت Exceptionها استفاده میکنیم. در این فصل با این دستورات آشنا میشویم.

مدیریت Exception ها

در فصل قبل مشاهده کردید که اگر خطایی در برنامه به وجود آید یک exception به وسیله CLR و یا کد برنامه ایجاد می شود. exception تولید شده برای جلوگیری از شکست برنامه باید مدیریت شود.

سی شارپ شامل دستوراتی است که با استفاده از آنها می توان exception ها را مدیریت کرد. سی شارپ از بلاکهای catch ، try و finally برای این منظور استفاده می کند :

try
{
    // code that may raise exceptions
}
catch(Exception ex)
{
    // handle exception
}
finally
{
    // final cleanup code
}

همانطور که در قاعده نوشتاری بالا مشاهده می کنید باید کدی را که ممکن است باعث بروز خطا شود در بلاک try قرار دهیم و به دنبال آن از بلاک های catch و یا finally استفاده کنیم. بعد از رخداد استثنا در بلاک try کدهای بلاک catch برای مدیریت آن استثنا اجرا می شوند.

بیایید از try و catch در یک نمونه مثال واقعی استفاده کنیم. به نمونه مثال زیر که باعث ایجاد یک exception می‌شود دقت کنید :

class Program
{
    static void Main(string[] args)
    {
        Console.Write("Enter Student Name: ");
        string studentName = Console.ReadLine();
        IList<String> studentList = FindAllStudentFromDatabase(studentName);
        Console.WriteLine("Total {0}: {1}", studentName, studentList.Count());
        Console.ReadKey();
    }
    private static IList<String> FindAllStudentFromDatabase(string studentName)
    {
        var studentList = // find all students with same name from the database 
        return studentList;
    }
}

نمونه کد بالا قرار است نام دانش آموزی را از کاربر دریافت کرده و همه دانش آموزانی با آن نام را از دیتابیس واکشی کند. کد بالا برای زمانی که جستجو در دیتابیس حداقل شامل یک دانش آموز باشد به خوبی کار می کند. اما در صورتی که دانش آموزی پیدا نشود استثنای NullReferenceException روی می دهد.

ما نمی خواهیم پیغام خطای exception ، مستقیم به کاربر نشان داده شود. بنابراین آن را با بلاک های try و catch مدیریت می‌کنیم :

class Program
{
    static void Main(string[] args)
    {
        Console.Write("Enter Student Name: ");
        string studentName = Console.ReadLine();
        
        try
        {
            IList<String> studentList = FindAllStudentFromDatabase(studentName);
            Console.WriteLine("Total {0}: {1}", studentName, studentList.Count());
        }
        catch(Exception ex)
        {
            Console.Write("No Students exists for the specified name.");
        }
        Console.ReadKey();
    }
    private static IList<String> FindAllStudentFromDatabase(string studentName)
    {
        var studentList = // find all students with same name from the database 
        return studentList;
    }
}

همانطور که در نمونه مثال بالا مشاهده می کنید زمانیکه studentList دارای مقدار null باشد، ()studentList.Count باعث رخداد یک استثنا می شود. به همین دلیل آن را داخل یک بلاک try قرار می‌دهیم.

نکته : به دنبال بلاک try باید از بلاک های catch یا finally و یا هر دو استفاده نمود. استفاده از بلاک try به تنهایی باعث به وجود آمدن خطای کامپایلری می‌شود.

بلاک Catch

استثناهایی که داخل بلاک try تولید می‌شود به وسیله کد های بلاک catch مدیریت می شود. کدهایی که در بلاک catch قرار می گیرند تنها زمانی اجرا می‌شوند که یک استثنا رخ دهد. در صورتی که نوع استثنا برای ما مهم باشد می‌توان از چندین بلوک catch به دنبال بلاک try استفاده کرد. در این صورت بسته به نوع استثنا ، کد مربوط به بلاک catch مورد نظر اجرا می‌شود :

class Program
    {
        static void Main(string[] args)
        {
            Console.Write("Please enter two numbers: ");
            try
            {
                int num1 = int.Parse(Console.ReadLine());
                int num2 = int.Parse(Console.ReadLine());
                int result = num1 / num2;
                Console.WriteLine("{0} / {1} = {2}", num1, num2, result);
            }
            catch (DivideByZeroException ex)
            {
                LogError(ex);
                Console.Write("Cannot divide by zero. Please try again.");
            }
            catch (InvalidOperationException ex)
            {
                LogError(ex);
                Console.Write("Not a valid number. Please try again.");
            }
            catch (FormatException ex)
            {
                LogError(ex);
                Console.Write("Not a valid number. Please try again.");
            }
            Console.ReadKey();
        }
    }

نمونه مثال بالا بسته به علت استثنا پیغام مناسبی را به کاربر نشان می دهد.

نکته : زمانی که از چندین بلاک catch استفاده می کنید نمی توانید از Exception یکسان برای آنها استفاده کنید.

 

زمانی که از چندین بلاک catch استفاده می کنید ، نمی‌توان از بلاک catch بدون پارامتر و بلاکی که دارای پارامتر Exception است، به طور همزمان استفاده کرد. زیرا که هر دوی آنها یکی هستند :

try
{
                    //code that may raise an exception
}
catch //cannot have both catch and catch(Exception ex)
{ 
                    Console.WriteLine("Exception occurred");
}
catch(Exception ex) //cannot have both catch and catch(Exception ex)
{
                    Console.WriteLine("Exception occurred");
}

همچنین باید دقت داشته باشید که بلاک catch بدون پارامتر و یا بلاک catch که شامل استثنای Exception است، باید همیشه آخرین بلاک باشد. نمونه مثال زیر با خطا روبرو می شود :

try
{
    //code that may raise an exception
}
catch
{ 
    // this catch block must be last block
}
catch (NullReferenceException nullEx)
{
    Console.WriteLine(nullEx.Message);
}
catch (InvalidCastException inEx)
{
    Console.WriteLine(inEx.Message);
}

Finally

بلاک finally همیشه بعد از بلاک try و یا catch می‌آید. کد های بدنه ی finally چه استثنا رخ دهد و چه رخ ندهد همیشه اجرا خواهند شد :

static void Main(string[] args)
{
    int zero = 0;    
    
    try
    {
        int result = 5/zero;  // this will throw an exception       
    }
    
    catch(Exception ex)
    {
        Console.WriteLine("Inside catch block. Exception: {0}", ex.Message );
    }
    
    finally
    {
        Console.WriteLine("Inside finally block.");
    }
}

خروجی نمونه مثال بالا به شکل زیر است :

Inside catch block. Exception: Attempted to divide by zero. Inside finally

نکته : ‌نمیتوان از چندین بلاک finally استفاده نمود. همچنین بلاک finally نمیتواند شامل دستورات return ، continue و break باشد

try-catch تو در تو

سی شارپ اجازه می‌دهد دستورات try-catch را به صورت تو در تو به کار ببریم.

static void Main(string[] args)
{
    Student std = null;
           
    try
    {
        try
        {
            std.StudentName = "";
        }
        catch
        {
            Console.WriteLine("Inner catch");
        }
    }
    catch
    {
        Console.WriteLine("Outer catch");
    }
}

خروجی نمونه مثال بالا به شکل زیر است :

Inner catch

 



شاید از نوشته‌های زیر خوشتان بیاید
نظر خود را درباره این پست بنویسید ...

منوی سریع