PDA

View Full Version : آموزش: مطالبی در مورد Try ..Catch ... Finally



فرید نجفلو
سه شنبه 12 اردیبهشت 1391, 13:27 عصر
با سلام
یکی از دوستان در یک پیغام خصوصی در مورد Try ..Catch ... Finally گفته و حتی پیشنهاد داده بودند که از On Error Resume Next استفاده شود به این دلیل که در آن از Exception خبری نیست!
چون این سوال ممکن است برای سایر دوستان نیز پیش آمده باشد بنده صلاح دانستم به آن صورت عمومی جواب دهم

به دلیل نامناسب بودن پست اول به خاطر وجود تبلیغات کناری ادامه در پست بعد آمده است

فرید نجفلو
سه شنبه 12 اردیبهشت 1391, 13:31 عصر
توجه کنید که On Error Resume Next یکی از امکانات جلو گیری و رسیدگی به خطا ها در VB6 بود که در جریان ارث بری VB.Net از آن و همچنن سازگاری آن با کد های VB6 به داخل VB.Net نیز وارد شده
البته من در مورد رسیدگی به خطا ها فکر نمی کنم چننین اسم کلی را بر روی آن نهاد

همان طور که می دانید در VB6 یک دستور دیگر هم به صورت On Error GOTO داشتیم که با ترکیب این دو دستور می توانستیم خطا ها را کنترل کنیم و این دستور نیز همچنان در VB.Net وجود دارد
اما بعد از ظهور دات نت با به وجود آمدن Try ..Catch ... Finally دستورات فوق منسوخ و کنار گذاشته شدند (با آنکه برنامه نویسان سابق VB6 و مبتدی در دات نت همچنان می توانند از آنها استفاده نمایند)

باید متذکر شد که قدرت Try ..Catch ... Finally بسیار بالاتر از آن دو دستور قدیمی می باشد که در ادامه شاهد خواهید بود

در مورد گفته و دلیل دوستون که گفته بودند از Exception خبری نیست باید گفت که درست است Exception ما را به یاد مشکلات می اندازد و هیچ وقت دوست نداریم آنها را ببینم ولی همیشه اینطور نیست Exception ها نیز جزئی از برنامه نویسی هستند و در جای خود بسیار مفیدند برای مثال ممکن است شما برنامه خود را طوری نوشته اید که هیچ گونه خطایی ندارد (که البته این کار تقریبا غیر ممکن می نماید) ولی شما هیچ تضمینی ندارید که از عوامل خارجی همچون اشتباهات کاربر، کتابخانه (DLL) های مورد استفاده ، سیستم عامل ، سخت افزار و غیره خطایی وارد برنامه شما نشده و شما را دامن گیر نکند
پس حال که می دانیم ممکن است با Exception ها به طور حتم در گیر شویم بهتر نیست بدانیم آن خطایی که رخ داده چه بوده و دلیل آن چه می باشد؟
ایا اینکه با سرپوش گذاری روی یک خطا ما باید خود را دل خوش کنیم که خطا های موجود را رفع کردیم؟!! یعنی چیزی مثل پاک کردن مسئله نه حل کردن آن!!!
(توضیح اینکه وقتی از On Error Resume Next استفاده می شود زمانی که یک خطا در یک خط رخ داد آن خط نادیده گرفته شده و اجرا نمی شود و برنامه به خط بعدی می رود)
حال اگر این خط یک خط حیاتی بود مثل پر کردن مقدار یک متغیر حساس اگر آن خط را رد کنیم برنامه در خطوط بعدی از مقدار قبلی آن یا در بدترین حالت مقدار پیش فرض (برای مثال برای انواع عددی صفر) را استفاده خواهد کرد که این ممکن است به یک فاجعه تبدیدل شود (مثلا زمانی که این اطلاعات در پایگاه داده ذخیره خواهند شد!)

البته بیشتر اوقات On Error GOTO بهتر از On Error Resume Next عمل می کند و اما این دستور نیز قدرت کافی برای مبارزه با Try ..Catch ... Finally را ندارد برای مثال تشخیص دقیق خطای روی داده!

مخصوصا در مورد Try ..Catch ... Finally تو در تو آن دو دستور به هیچ وجه به پای این نخواهند رسید

حالا به کد زیر توجه کنید بیشتر توضیحات در داخل آن به صورت کامنت شده قرار دارد:


'حالت کلی به شکل زیر می باشد
Try
'Normal Code Body
Catch ex As Exception
'Exception(Error) Handeling Code Body
Finally
'Must Run(Very Important) Code Body
End Try
'حال توضیحات:
Try
'*****
'شروع برنامه
'انجام کار های مورد نیاز، برای مثال باز کردن فایل
'*****
'ما می توانیم از
'Try ... Catch
'تو در تو استفاده کنیم
'برای مثال در چند خط بعدی به هیچ عنوان نمی خواهیم
'خطا های به وجود آمده، برنامه ما را متوقف کند یا به کاربر نشان داده شود
Try
'اگر در این قسمت خطایی رخ دهد اجرای برنامه به خط "ادامه برنامه" منتقل می شود
Catch ex As Exception
'توجه کنید این قسمت خالی است
End Try
'*****
'ادامه برنامه
'برای مثال عملیات خواندن و نوشتن فایل
'*****
'در این قسمت برنامه به پایان می رسد(خط آخر) و قسمت "بررسی خطا ها " اجرا نخواهد شد
' درصورتی که بدنه
'Finally
'وجود داشته باشد آن نیز اجرا می شود سپس
'اجرای برنامه به قسمت
'عملیت خارج از
'Try ... Catch
'منتقل می شود (البته در صورت وجود)
'و خروج صریح از برنامه ادامه کد ها را نادیده خواهد گرفت

'بروز خطا ها در خطوط بعدی بررسی می شود
'به کد های زیر دقت کنید
'شما می توانید دقیقا خطا را فیلتر کنید
'و در صورت نیاز عملیات رفع خطای مطابق با آن خطا را انجام دهید
'یک نکته مهم اینکه در صورت بروز خطا فقط یکی از بدنه های
'Catch
'اجرا شود و آن بدنه ای است که اولین مطابقت را با نوع خطا دارد و پس از
'آن بقیه کد های رسیدگی به خطا اجرا نخواهند شد و
' توجه کنید که ترتیب قرار گیری بسیار مهم می باشد برای مثال بعد از
'Catch ex As Exception
'هیچ یک ااز رسیدگی ها اجرا نخواهند شد زیرا رسیدگی کننده بالا
'تمام انواع خطا ها را به دام می اندازد
'و این کد باید وجود داشته باشد زیر ممکن است هیچ کدام از رسیدگی کننده های پیش بینی شده خطا را گرفتار
'نکند پس این رسیدگی کننده آن را گرفتار خواهد کرد
'بهترین مکان آن هم قرار گرفتن به عنوان آخرین رسیدگی کننده است
'بعد از رسیدگی به خطا درصورتی که بدنه
'Finally
'وجود داشته باشد آن نیز اجرا می شود سپس
'اجرای برنامه به قسمت
'عملیت خارج از
'Try ... Catch
'منتقل می شود (البته در صورت وجود)

'***** شروع قسمت بررسی خطا ها ******
Catch ex As IO.FileNotFoundException 'مثال
'فایل موجود نبود
'اگر فایل توسط برنامه ایجاد می شود عملیات ایجا فایل انجام
'یا اگر کاربر فایل را مشخص می کند فایل از کاربر در خوست می شود
'سپس اقدام به تلاش مجدد می شود
Catch ex As UnauthorizedAccessException 'مثال
'خطای دسترسی غیر مجاز
'می توانید عملیات را متوقف کنید و به کار هشدار دهید که
'مجوز لازم وجود ندارد شاید لازم باشد برنامه به صورت
'Run As Administrator
'اجرا شود (البته در ویندوز ویستا ، 7 و بالاتر
MsgBox("خطا در عملیات" & vbNewLine & "شما مجوز کافی به برنامه اعطا نکرده اید" & _
vbNewLine & ex.Message)
Catch ex As Exception
'به احتمال زیاد خطا نا شناخته است و یا ما پیش بینی آن را
'نکرده بودیم پس به کاربر پیام خطا نمایش می دهیم
MsgBox("خطا در عملیات" & vbNewLine & ex.Message)
'***** اتمام قسمت بررسی خطا ها ******
Finally '*** مهم ****
'این قسمت از کد چه خطا وجود داشته باشد یا
'وجود نداشته باشد به طور حتم اجرا خواهد شد
'برای مثال می توانید تمام فایل های باز شده را اینجا ببنید
'توجه کنید ممکن است در این نقطه هم خطا بروز کند اگر
'از عدم بروز خطا مطمئن نیستید اینجا هم می توانید از
'Try ... Catch
'استفاده کنید
End Try
'عملیت خارج از
'Try ... Catch


بهتر است کد های بالا را در ویژوال استیو کپی و آنجا مطالعه کنید (اینجا خونایی لازم را ندارد)
توضیحات بیشتر:
در استفاده از Try ..Catch ... Finally باید یکی از ترکیب های زیر استفاده شود:


'1:
Try
Catch ex As Exception
Finally
End Try
'2:
Try
Catch ex As Exception
End Try
'3:
Try
Finally
End Try


همانطور که گفته شد Finally در صورت وجود یا عدم وجود به هر حال اجرا خواهد شد ولی اگر ما به صورت صریح از داخل متد یا تابع خارج شویم اجرا نخواهد شد برای مثال این دستورات صریح می باشند Exit Sub , Exit Function , Return

شما برای مکان استفاده از Try ..Catch ... Finally اختیارات فراوانی دارید
به کد زیر دقت کنید:

For i As Integer = 1 To 100
Try
'انجام عملیات
Catch ex As Exception
End Try
Next


حلقه فوق به طور حتم 100 بار اجرا خواهد شد حتی اگر درون آن خطایی به وجود آید!

نکته ای در مورد Exception ها :
شما خود می توانید یک Exception (خطای) مورد نیاز را راه اندازی کنید (که در VB6 چنین امکانی وجود ندارد)

Try
If Not IO.File.Exists("C:\ImportantFile.Txt") Then
'تشخیص داده شد این فایل وجود ندارد
'پس ادامه برنامه امکان پذیر نمی باشد
Throw New IO.FileNotFoundException("فایل مورد نیاز برنامه پیدا نشد این فایل برای ادامه برنامه ضروری می باشد")
End If
Catch ex As IO.FileNotFoundException
'اگر خطای شما راه اندازی شود این قسمت به اجرا در خواهد آمد
MsgBox(ex.Message)
Catch ex As Exception
End Try