آموزش گام به گام #C (جلسه پانزدهم: معرفی کنترل خطا و Exception)
1398/01/19 12:20 , میلاد صاحب نظر

آموزش گام به گام #C (جلسه پانزدهم: معرفی کنترل خطا و Exception)

مسلما تا الان با ارورهایی مواجه شده‌اید که علی‌رغم درست بودن منطق کد و تفکر شما، رخ داده‌اند. گاهی نمی‌توانید بفهمید دقیقا مشکل از کدام قسمت کد رخ می‌دهد؟ راه حل چنین وضعیت‌هایی چیست؟ با ما همراه باشید!

جلسه اول: آغاز کار با #C جلسه ششم: namespaceها جلسه یازدهم: اندیس گذار یا indexerها جلسه شانزدهم: استفاده از اتریبیوت‌ها جلسه بیست و یکم: متدهای بی‌نام یا anonymous
جلسه دوم: عملگرها، نوع‌ها و متغیرها جلسه هفتم: مقدمه‌ای بر کلاس‌های #C جلسه دوازدهم: ساختار یا structها جلسه هفدهم: enumها جلسه بیست و دوم: موضوعاتی در مورد نوع در #C
جلسه سوم: عبارات کنترلی - گزینشی جلسه هشتم: وراثت کلاس در #C جلسه سیزدهم: واسط یا interfaceها جلسه هجدهم: عملگرهای overloading جلسه بیست و سوم: کار با نوع‌های nullable
جلسه چهارم: عبارات کنترلی - حلقه‌ها جلسه نهم: چندریختی جلسه چهاردهم: مقدمه‌ای بر delegateها و رویدادها جلسه نوزدهم: کپسوله‌سازی  
جلسه پنجم: متدها جلسه دهم: ویژگی یا propertyها جلسه پانزدهم: مقدمه‌ای بر کنترل خطا یا exception جلسه بیستم: مقدمه‌ای بر generic collectionها  

در این جلسه، نحوه کنترل خطا و Exceptionها در برنامه‌های #C را بررسی خواهیم کرد. اهداف ما به شرح زیر هستند:

  • آموختن مفهوم Exception
  • پیاده‌سازی یک روتین با یک قطعه کد یا بلوک try / catch
  • انتشار منابع در یک بلوک finally

Exceptionها

Exceptionها ارورهای پیش‌بینی نشده‌ای هستند که در برنامه‌های شما اتفاق می‌افتند. در اکثر مواقع، می‌توانید (و باید) ارور‌های برنامه را در کد خود شناسایی و کنترل کنید.

برای مثال، اعتبارسنجی ورودی کاربر، بررسی null بودن اشیاء و شناسایی مقادیر بازگردانده شده از متدها حیطه‌هایی هستند که باید از آن‌ها انتظار ارور داشته باشید و در تمام مدت کد نویسی در همه این حیطه‌ها باید یک استراتژی کنترل خطای استاندارد اعمال کنید.

به هر حال، اوقاتی هستند که شما مطمئن نیستید آیا اروری رخ می‌دهد یا خیر. برای مثال، نمی‌توانید پیش‌بینی کنید چه موقع یک ارور فایل I/O دریافت خواهید کرد، چه موقع حافظه سیستم تمام می‌شود یا چه موقع با ارور پایگاه داده مواجه خواهید شد.

وقوع چنین خیلی بعید است، اما به هر حال ممکن است اتفاق بیفتند و شما باید بتوانید در صورت رخ دادن، آن‌ها را کنترل کنید. این جا است که کنترل Exception وارد عمل می‌شود.

وقتی Exceptionها اتفاق می‌افتند، اصطلاحا از واژه thrown یا پرتاب استفاده می‌شود. چیزی که در واقع thrown می‌شود، شیئی است که از کلاس System.Exception مشتق شده است. در بخش بعدی، توضیح خواهم داد که چگونه می‌توان Exceptionهای thrown شده را با بلوک‌های try/catch کنترل کرد.

کلاس System.Exceptionچندین متد و Property برای به دست آوردن اطلاعات در مورد مشکلی که به وجود آمده است، فراهم می‌کند.

برای مثال، Message Property اطلاعات مختصری از اینکه خطا در مورد چیست فراهم می‌کند، stacktrace property اطلاعاتی از وضعیت stack و مشکلی که در آن به وجود آمده فراهم می‌کند و متد ()ToString بازنویسی یا override می‌شود تا توصیف کاملی از کل exception نمایش دهد.

شناسایی Exceptionهایی که باید کنترل کنید به روتینی که می‌نویسید بستگی دارد. برای مثال، اگر روتین فایلی با متد ()System.Iofile.OpenRead باز کند، ممکن است هر کدام از Exceptionهای زیر thrown شوند:

  • SecurityException
  • ArgumentException
  • ArgumentNullException
  • PathTooLongException
  • DirectoryNotFoundException
  • UnauthorizedAccessException
  • FileNotFoundException
  • NotSupportedException

با بررسی فایل مستند SDK در NET Framework.، می‌توانید خیلی راحت متوجه شوید که یک متد ممکن است چه exceptionهایی را thrown کند. فقط کافی است به بخش کتابخانه Refrence/Class بروید و در سند Namespace/Class/Method به دنبال متدهایی که استفاده کرده‌اید بگردید.

Exceptionهای موجود در لیست بالا با بررسی تعریف متد ()OpenRead از کلاس File در System.Ionamespace یافته شده‌اند. هر exception شناسایی شده دارای یک هایپرلینک به سمت تعریف کلاس خود است، که می‌توانید از آن برای یافتن exceptionها و معانی و دلایل وقوع آن‌ها بهره ببرید.

وقتی فهمیدید که چه exceptionهایی ممکن است در کد شما رخ دهند، باید مکانیزم‌هایی برای کنترل آن‌ها (البته در صورت وقوع) پیاده‌سازی کنید.

بلوک‌های try / catch

وقتی exceptionها thrown می‌شوند، باید بتوانید آن‌ها را کنترل کنید. این کار با پیاده‌سازی یک بلوک try/catch انجام می‌شود. کدی که ممکن است یک exception را thrown کند، در بلوک try و کد کنترل exception در بلوک catch قرار می‌گیرد.

لیست ۱-۱۵  چگونگی پیاده‌سازی یک بلوک try/catch را نشان می‌دهد. چون یک متد ()OpenRead می‌تواند یکی از آن چند exception بیان شده را throw کند، پس در بلوک try قرار گرفته است. اگر exception رخ دهد یا thrown شود، در بلوک Catch به دام می‌افتد.

کد موجود در لیست ۱-۱۵ پیامی چاپ می‌کند و در صورت وقوع یک exception، اطلاعات تریس Stack یا پشته را در کنسول چاپ می‌کند.

نکته: برنامه‌های موجود در این جلسه از عمد exception ایجاد می‌کنند. Exceptionی که شما مشاهده می‌کنید از عمد ایجاد می‌شود تا قبل از اینکه خودتان تجربه کنید، به شما نمایش دهد که پیغام exception چگونه است.
لیست ۱-۱۵. استفاده از بلوک‌های try/catch: tryCatchDemo.cs

اگرچه کد موجود در لیست ۱-۱۵ فقط دارای یک بلوک Catch است، اما همه exceptionها در آن به دام می‌افتند، چون نوع آن از نوع پایه‌ای و اولیه خود exception است. در کنترل exception، پیش از اینکه exceptionهای پدر و کلی به دام بیفتند، exceptionهای خاص و مشتق گرفته شده به دام می‌افتند.

برای مثال، قطعه کد زیر چگونگی نوشتن چندین بلوک catch را نمایش می‌دهد:

اگر فایل وجود نداشته باشد، یک FileNotFoundException رخ می‌دهد و توسط اولین بلوک catch گرفتار می‌شود. به هر حال، اگر یک PathTooLongException رخ دهد، دومین بخش Catch آن Exception را به دام می‌اندازد.

این بدان دلیل است که هیچ بلوک catch مخصوص به دام انداختن PathTooLongException وجود ندارد و تنها گزینه موجود برای به دام انداختن Exception، بلوک catch دارای نوع کلی و اولیه Exception است. 

Exceptionهایی که کنترل نمی‌شوند، طبیعتا به صورت یک پیغام حبابی در پشته ظاهر می‌شوند و تا زمانی که یک روتین در زنجیره فراخوانی آن‌ها را کنترل کند، ادامه می‌یابند.

اگر فراموش کردید که در بخشی از کد خود بلوک‌های try/catch به کار ببرید و از قبل هم هیچ بلوک try/catch در زنجیره فراخوانی وجود نداشته باشد، بنابراین برنامه شما با یک پیغام که Exception را توضیح می‌دهد، پایان می‌یابد.

از نظر کاربران، وقوع چنین پیغامی بسیار غیر حرفه‌ای و ناراحت کننده‌ است. پس همیشه استراتژی کنترل Exception را در برنامه‌های خود به کار بگیرید.

بلوک‌های finally

یک Exception با آزاد نکردن منابع یا آزاد نکردن حافظه، برنامه شما را در وضعیت ناسازگاری و اختلال قرار می‌دهد. بلوک Catch، روش خوبی برای درک مشکل و برطرف کردن آن است، البته این روش برای تمام سناریوها و وضعیت‌ها پاسخگو نیست.

گاهی علی‌رغم اجرای موفق یا ناموفق برنامه خود، لازم است اعمال خالی کردن حافظه را انجام دهید. چنین وضعیت‌هایی، موقعیت‌های مناسبی برای به کار بردن بلوک finally هستند.

لیست ۲-۱۵ مزیت استفاده از یک بلوک Finally را نشان می‌دهد. همان‌طور که می‌دانید، وقتی کارتان با یک جریان فایل تمام شد، باید آن را ببندید. در این مورد، جریان فایل، همان منبعی است که باید آزاد شود. در لیست ۲-۱۵، outStream با موفقیت باز شده است، یعنی اینکه برنامه یک منبع فایل باز را کنترل می‌کند.

وقتی سعی می‌کنید inStream را باز کنید، یک FileNotFoundException‌رخ می‌دهد، در نتیجه کنترل، سریعا برنامه را به بلوک Catch می‌برد.

بستن outStream در بلوک Catch امکان‌پذیر است، اما اگر الگوریتم بدون وقوع exception، با موفقیت اجرا شود چطور؟ در صورت موفقیت اجرای الگوریتم، فایل هیچ‌گاه بسته نمی‌شود.

خوشبختانه، ما یک بلوک finally در لیست ۲-۱۵ قرار دادیم، که همیشه اجرا می‌شود. درست است، مهم نیست الگوریتم در بلوک‌های try دچار exception شد یا خیر، به هر حال قبل از اینکه کنترل از این متد خارج شود، کدهای درون بلوک finally اجرا می‌شوند.

لیست ۲-۱۵. پیاده‌سازی یک بلوک finally: FinallyDemo.cs

استفاده از بلوک finally اجباری نیست و تعجبی ندارد اگر بپرسید: چه اتفاقی می‌افتد اگر ما فقط کد را به صورت معمولی بعد از بلوک catch‌قرار دهیم؟

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

برای مثال، اگر یکی از کنترل کننده‌های catch دوباره همان Exception را ایجاد کند یا باعث به وجود آمدن یک Exception دیگر شود، کد قرار گرفته بعد از بلوک Catch (نه کد موجود در بلوک finally) هیچ‌گاه اجرا نخواهد شد.

همچنین، اگر اصلا Exceptionها را به دام نیندازید، جریان برنامه سریعا وارد پشته می‌شود و به دنبال یک کنترل کننده Exception می‌گردد که مناسب آن Exception باشد و کد قرار گرفته بعد از بلوک‌های Catch اجرا نخواهد شد.

چون پتانسیل خیلی زیادی برای اجرا نشدن کد موجود در یک الگوریتم وجود دارد، وجود یک بلوک finally برای اجرا شدن کدهای خطر دار، لازم است.

خلاصه

در این جلسه، مقدمه‌ای از کنترل Exceptionها بیان شد. تا الان، باید درک خوبی از مفهوم Exception به دست آورده باشید. باید بتوانید الگوریتم‌های خود را درون بلوک‌های try/catch (که Exceptionها را کنترل می‌کنند) پیاده‌سازی کنید.

علاوه بر این، می‌دانید که چطور با پیاده‌سازی یک بلوک finally (که کد داخل آن قبل از خارج شدن برنامه از متد، همیشه اجرا می‌شود) منابع برنامه خود را آزاد کنید.

منبع: C#-Station

جلسه بعد                                                                جلسه قبل

 مطالب مرتبط

 مقدمه ای بر زبان برنامه نویسی #C و پلتفرم NET Framework.
7 دلیل منطقی برای آموختن #C
 طبقه بندی زبان های برنامه نویسی
به دست آوردن Exceptionها در #C و یافتن همه خطاها
 LINQ(زبان جستجوی یکپارچه)
برنامه نویسی شیءگرا چیست؟

از آخرین دوره های آموزشی و تخفیف ها مطلع شوید

با تکمیل فرم زیر ، از اخبار و اطلاعات به روز برنامه نویسی و تکنولوژی عقب نمانید

آخرین مطالب

آموزش جامع SQL Server (جلسه ۱۲)
آموزش جامع SQL Server (جلسه ۱۲)

دستور UPDATE در SQL Server برای تغییر داده‌های موجود در یک جدول، از دستور UPDATE به شکل زیر استفاده ...

آموزش جامع SQL Server (جلسه ۱۵)
آموزش جامع SQL Server (جلسه ۱۵)

دستور DROP TABLE در SQL Server گاهی، لازم است یک جدول که دیگر استفاده‌ای ندارد را حذف کنید. برای ...

آموزش جامع SQL Server (جلسه ۳۵: Window Functionها – بخش ۲)
آموزش جامع SQL Server (جلسه ۳۵: Window Functionها – بخش ۲)

بخش اول از آخرین مبحث دوره جامع آموزش SQL Server در جلسه قبلی بررسی شد. این مبحث که ...

آخرین دیدگاه ها

دیدگاه خود را درباره این پست بنویسید

فرم ارسال نظرات