PDA

View Full Version : مبتدی: try...catch چیست و چه کاربردی دارد؟



nimamohammadi
پنج شنبه 20 اسفند 1388, 10:03 صبح
سلام
لطفا درمورد نحوه عملکرد این کد برام توضیح بدید ممنون


try
{
}
catch
{
}

saed2006
پنج شنبه 20 اسفند 1388, 10:14 صبح
try یعنی تلاش
یعنی تلاش کن تا قطعه کدی که داخل try هست رو اجرا کنی
و اگر با خطامواجه شدی catch را اجرا کن
همین

peymanjon
پنج شنبه 20 اسفند 1388, 11:57 صبح
pdf آقای هاشمیان را از این آدرس دانلود کن و قسمت try &catch را مطالعه کنید.
http://www.farsiebook.com/ebook/7359.htm
موفق باشید

mehdi.mousavi
پنج شنبه 20 اسفند 1388, 12:08 عصر
سلام.
اگر موافقید بحث رو فنی کنیم تا این تاپیک حداقل دارای یک بار علمی هم بشه... همه میدونیم که try...catch به چه درد میخوره و همونطوریکه saed2006 توضیح دادن، برای اجرای Block ای از کد در try، تعامل با خطاها در catch block و آزادسازی منابع در finally هستش.

اما چه کسی میتونه توضیح بده اشکال (یا اشکالات) کدی که nimamohammadi نوشتن، چی هستش و چرا نباید از چنین Code Snippet ای استفاده کرد؟

موفق باشید.

behzad1986
پنج شنبه 20 اسفند 1388, 12:24 عصر
سلام Exception نداره و اين باعث ميشه برنامه خطا نگيره وما از خطا مطع نميشيم

saed2006
پنج شنبه 20 اسفند 1388, 12:31 عصر
سلام.
اگر موافقید بحث رو فنی کنیم تا این تاپیک حداقل دارای یک بار علمی هم بشه... همه میدونیم که try...catch به چه درد میخوره و همونطوریکه saed2006 توضیح دادن، برای اجرای Block ای از کد در try، تعامل با خطاها در catch block و آزادسازی منابع در finally هستش.

اما چه کسی میتونه توضیح بده اشکال (یا اشکالات) کدی که nimamohammadi نوشتن، چی هستش و چرا نباید از چنین Code Snippet ای استفاده کرد؟

موفق باشید.

استاد موسوی رویه جالب و کم نظیری رو پی گرفته اید
اینکه در یه تایپیک پیرامون موضوع تاپیک به نتیجه قابل قبولی برسیم کار پسندیده ای هست
من به نوبه خودم تشکر میکنم از این اقدام شما و امیدوارم مدیران دیگر هم این رویه رو در پیش بگیرن
به هر حال خسته نباشید

mehdi.mousavi
پنج شنبه 20 اسفند 1388, 12:45 عصر
سلام Exception نداره و اين باعث ميشه برنامه خطا نگيره وما از خطا مطع نميشيم

خیر. در واقع تفاوتی بین این دو Code Block وجود نداره:

try
{
}
catch
{
}

try
{
}
catch(Exception ex)
{
}


به بیان دیگه، هر Exception ای که در هر دو block فوق رخ بده، catch اونها رو خواهد گرفت و شما از خطا مطلع خواهید شد. اما هر دو ایراد (هایی) دارن. کسی میتونه به این ایرادها اشاره کنه؟

من روز شنبه پاسخ رو براتون مینویسم، تا اونموقع هر کسی نظری داره میتونه مطرح کنه.

موفق باشید.

amirj00n_001
پنج شنبه 20 اسفند 1388, 14:00 عصر
اگر ما بتونیم در طراحی برنامه خطا هایی که برای ما پیش میاد رو شناسایی کنیم می توانیم در تولید کد موفق تر باشیم اما هدف از این بحث این بود که ما می توانیم با خطا هایی که ممکن است در برنامه رخ دهد آنها را طوری تولید کنیم که در موقع برخورد با خطا ها مختلف استثنا های مختلفی را اجرا کنند که همانطور که در دو ساختار بالا می بینم این استثنا برای هر ساختاری تنها یک کد اجرا می شود و برای خطاهای مختلف هیچ برنامه ریزی ندارد به نظر من این از عیب های این برنامه می باشد.
معرفی چند استثنا
Access ViolationException
Format Exception
ArgumentException
DataException
RankException
ReadonlyException
و ....
حال ما می توانیم برای اینها استثنای مختلف را تولید کنیم.

hakelberfin
پنج شنبه 20 اسفند 1388, 17:13 عصر
سلام
با تشکر استاد موسوی به خاطر بحث جالبشون

به نظر من Try ...Catch اول ایرادش اینه که هر Exception ای رو به دام میندازه و ممکنه که این Exception اصلا در واقع خطا یا استثنا نباشه .(بعضی از دستورات سیستم عامل یا دیگر نرم افزارهای در حال اجرا)
Try...Catch دوم هم همین ایراد رو داره ولی نه به این شدت.

CYCLOPS
پنج شنبه 20 اسفند 1388, 17:27 عصر
من یه PDF مختصر در این مورد نوشتم میتونید از این (http://barnamenevis.org/forum/showthread.php?t=154472)لینک و یا از لینک امضام ازش استفاده کنید .
امیدوارم براتون مفید باشه . . . :چشمک:

Rejnev
پنج شنبه 20 اسفند 1388, 18:39 عصر
یک نکته کوچولو رو هم من بگم اینه که
اگر قطعه کدی که در catch نوشته میشه دارای خطا باشه برنامه متوقف میشه. یعنی از catch رد نمیشه. مگر اینکه داخل catch هم دوباره try catch بذاریم
مثال تقسیم بر صفر:



int a = 10,
b = 0,
c;
try
{
c = a / b;
}
catch
{
c = a / b; //here application will be stopped
}


و یک چیز دیگه اونهم اینه که حتی الامکان اندازه try catch رو محدود کنید و سعی کنید روی قسمتهای حساس یک متد try catch داشته باشید.

Rejnev
پنج شنبه 20 اسفند 1388, 19:18 عصر
یک سوال داشتم اینه که چرا بلاکی که catch نداره(try finally) حین اجرا اگه در قسمت try خطا رخ بده برنامه crash میشه؟
مثلا در این کد connection string رو ندادیم:
عکس:


http://barnamenevis.org/forum/attachment.php?attachmentid=45468&stc=1&d=1268324282


اما اگه بجای finally کلمه catch بذاریم رد میشه. در کل کاربرد try finally چیه؟

mehdi.mousavi
جمعه 21 اسفند 1388, 01:42 صبح
یک سوال داشتم اینه که چرا بلاکی که catch نداره(try finally) حین اجرا اگه در قسمت try خطا رخ بده برنامه crash میشه؟ مثلا در این کد connection string رو ندادیم اما اگه بجای finally کلمه catch بذاریم رد میشه. در کل کاربرد try finally چیه؟

سلام.
خودتون میگید catch نداره. catch یعنی چی؟ یعنی "گرفتن". منظورش چیه؟ منظورش اینه که "خطا اگر توی try رخ داد، توی بلاک catch بگیرش". بنابراین وقتی catch رو نمیذارید، یعنی علاقه ای به گرفتن خطاهای احتمالی در try ندارید و در نتیجه، برنامه crash میکنه. (در واقع exception به یک level بالاتر منتقل میشه، اما چون میبینه شما Exception ها رو در اون سطح هم handle نکرده اید، برنامه crash میکنه).

try...finally به چه درد میخوره؟ فرض کنید میخواهید کاری انجام بدید، که بدون توجه به رخ دادن، یا ندادن خطا در بلاک try، میخواهید از فراخوانی کد خاصی مطمئن بشید. این کد رو در finally مینویسید. اگر کد نوشته شده در بلاک try با خطا مواجه بشه، اجرا به بلاک finally منتقل میشه و اونجا هر چی نوشته باشید اجرا میشه، سپس Exception مزبور throw میشه. اگر هم خطایی در try رخ نده، اجرا با به finally منتقل میشه، کد شما اجرا میشه، و اجرای مابقی کد موجود پس از بلاک finally پیگیری میشه.

موفق باشید.

CYCLOPS
جمعه 21 اسفند 1388, 19:18 عصر
البته در بعضی از مواقع بلاک finally اصلا اجرا نمیشه . . .
به این (http://vahidnasiri.blogspot.com/2009/05/finally.html)مطلب تو وبلاگ آقای وحید نصیری دقت کنید .

mehdi.mousavi
جمعه 21 اسفند 1388, 21:36 عصر
البته در بعضی از مواقع بلاک finally اصلا اجرا نمیشه . . .
به این (http://vahidnasiri.blogspot.com/2009/05/finally.html)مطلب تو وبلاگ آقای وحید نصیری دقت کنید .

سلام.
این مطلب چیر عجیبی نیست. مایکروسافت از نسخه .NET 2.0 به بعد، تصمیم گرفت StackOverflowException رو به چشم دیگه ای نگاه کنه... مایکروسافت متوجه این موضوع شد که اگر این Exception در برنامه رخ بده، برنامه نویس به احتمال بسیار زیاد قادر به بازگرداندن شرایط اجرایی به حالت نرمال نیست، و بهترین تصمیم، خامه Process هستش. بنابراین اگر به مثال آقای نصیری رجوع کنید، متوجه خواهید شد که بلاک catch هم هرگز اجرا نخواهد شد، چون به محض رخ دادن این خطا، Process بطور خودکار terminate میشه. البته در نسخه های .NET اولیه، جریان چیز دیگه ای بود، که توضیح اون از حوصله این بحث خارجه.

بنابراین، همه اینها رو گفتم که بگم، هیچ حالتی وجود نداره که بلاک finally اجرا نشه.

موفق باشید.

FastCode
جمعه 21 اسفند 1388, 22:47 عصر
همه اینها رو گفتم که بگم، هیچ حالتی وجود نداره که بلاک finally اجرا نشه..

دو سه روز پیش توی stack یه سوال رو میخوندم که دقیقا" خلاف حرف شما رو اثبات میکرد.

StackOverflowException
ExecutingEngineException
SecurityException

mehdi.mousavi
جمعه 21 اسفند 1388, 23:24 عصر
دو سه روز پیش توی stack یه سوال رو میخوندم که دقیقا" خلاف حرف شما رو اثبات میکرد.

StackOverflowException
ExecutingEngineException
SecurityException

سلام.
لطفا لینک به مطلبی رو که عنوان می کنید بذارید ببینم چی نوشته... مطلبی که عنوان کردم، توی MSDN هست:

Starting with the .NET Framework version 2.0, a StackOverflowException object cannot be caught by a try-catch block and the corresponding process is terminated by default. Consequently, users are advised to write their code to detect and prevent a stack overflow. For example, if your application depends on recursion, use a counter or a state condition to terminate the recursive loop. Note that an application that hosts the common language runtime (CLR) can specify that the CLR unload the application domain where the stack overflow exception occurs and let the corresponding process continue. For more information, see ICLRPolicyManager Interface (http://msdn.microsoft.com/en-us/library/ms164394.aspx) and Hosting the Common Language Runtime (http://msdn.microsoft.com/en-us/library/9x0wh2z3.aspx).

موفق باشید.

Himalaya
جمعه 21 اسفند 1388, 23:39 عصر
اگر به مثال آقای نصیری رجوع کنید، متوجه خواهید شد که بلاک catch هم هرگز اجرا نخواهد شد، چون به محض رخ دادن این خطا، Process بطور خودکار terminate میشه.
بنابراین، همه اینها رو گفتم که بگم، هیچ حالتی وجود نداره که بلاک finally اجرا نشه

موافقم... اون مثال هم یه جورایی داره به مطلب زیر اشاره میکنه (منظورم این نیست که دقیقا خود اینه ها،
ولی بی شباهت هم نیستن)
کتاب چگونه با C#‎ 2005 برنامه بنویسیم از DEITEL
صفحه 433 ، نکته آزمایش و خطایابی 11.4


تنها در یک مورد بلاک finally اجرا نخواهد شد و آن هنگامی است که در بلاک try دستور خروج از برنامه باشد

اینجا گفته زمانی که تو بلاک try دستور خروج ار برنامه باشه و تو مثال آقای نصیری اومده تو try یه تابع رو فراخونی کرده


static void TryAndTry()
{
try
{
TryAndTry();
}
catch (Exception exError)
{
Console.WriteLine(exError.Message);
}
finally
{
Console.WriteLine("Try: Finally...!");
}
}

که این تابع هم مدام خودش رو فراخونی میکنه که در مورد terminate شدن پروسس هم توضیح داده شد

FastCode
جمعه 21 اسفند 1388, 23:53 عصر
سلام.
لطفا لینک به مطلبی رو که عنوان می کنید بذارید ببینم چی نوشته... مطلبی که عنوان کردم، توی MSDN هست:

Starting with the .NET Framework version 2.0, a StackOverflowException object cannot be caught by a try-catch block and the corresponding process is terminated by default. Consequently, users are advised to write their code to detect and prevent a stack overflow. For example, if your application depends on recursion, use a counter or a state condition to terminate the recursive loop. Note that an application that hosts the common language runtime (CLR) can specify that the CLR unload the application domain where the stack overflow exception occurs and let the corresponding process continue. For more information, see ICLRPolicyManager Interface (http://msdn.microsoft.com/en-us/library/ms164394.aspx) and Hosting the Common Language Runtime (http://msdn.microsoft.com/en-us/library/9x0wh2z3.aspx).

موفق باشید.

یکی از لینکها این بود:
http://stackoverflow.com/questions/464098/does-a-finally-block-always-run
دو سه تا دیگه هم بود که باید دنبالشون بگردم ولی فکر میکنم OutOfMemoryException هم بود.

mehdi.mousavi
شنبه 22 اسفند 1388, 00:12 صبح
یکی از لینکها این بود:
http://stackoverflow.com/questions/464098/does-a-finally-block-always-run
دو سه تا دیگه هم بود که باید دنبالشون بگردم ولی فکر میکنم OutOfMemoryException هم بود.

سلام.
این لینکی که ارسال کرده اید پرسش مزبور رو در مورد Java مطرح کرده، نه .NET:

Is there any condition where finally might not run in java? Thanks.

FastCode
شنبه 22 اسفند 1388, 14:59 عصر
سلام.
این لینکی که ارسال کرده اید پرسش مزبور رو در مورد Java مطرح کرده، نه .NET:

Is there any condition where finally might not run in java? Thanks.

اشتباه کردم.:اشتباه::خجالت:
ولی این یکی از طرف نفر 8 stack مهرداد افشاری:
http://stackoverflow.com/questions/833946/in-c-will-the-finally-block-be-executed-in-a-try-catch-finally-if-an-unhandled

mehdi.mousavi
شنبه 22 اسفند 1388, 15:16 عصر
سلام.
امروز شنبه هستش و فرصت پاسخگویی به سوالی که مطرح کردم به سر رسیده. من لحظه اولی که تاپیک رو دیدم خواستم پاکش کنم، اما به یکباره این ایده به ذهنم رسید که میشه از یک تاپیک مرده، تاپیکی مفید و پویا ساخت. برای این بود که اون سوال رو مطرح کردم و نتیجه جالب بود، اگر چه انتظار داشتم تعداد افراد بیشتری در بحث شرکت کنن. همگی دیدیم که چطور از یک بلاک try...catch میشه این همه مطلب استخراج کرد. اینها رو گفتم که بگم: از این بعد هر تکه کدی که می نویسید یادتون باشه که پشتش ممکنه هزاران مطلب نهفته باشه. هیچ چیزی رو سرسری ازش نگذرید، قبل از اینکه بهش اشراف پیدا کنید. حالا بریم سر اصل مطلب. ایراد کد فوق چی بود؟

همونطوری که یکی از دوستان اشاره کردن، اولین ایراد کد مزبور این بود که کلیه خطاها بدون توجه به نوع خطا، داره تو بلاک catch گرفته میشه. فرض کنیم که تو بلاک try، متود BeginRead از FileStream رو فراخوانی کنیم. BeginRead ممکنه 4 Exception متفاوت throw کنه:



ArgumentException
ArgumentNullException
ArgumentOutOfRangeException
IOException



هر کدوم از این خطاها، باید جداگانه Handle بشن چون هر کدوم معانی متفاوتی دارن و نمیشه همه رو به یک چشم نگاه کرد. تازه از بین این 4 تا، باید فقط اونهایی catch بشن که واقعا قراره تو اون شرایط کاری انجام بشه. اگر قراره فقط ArgumentException رو catch کنید، و کاری انجام ندید، اصلا نیازی نیست که اونو catch کنید و باید نگران 3 تای بعدی باشید. وقتی ArgumentException رو handle نمی کنید، در واقع دارید این فرصت رو به تابع قبلی (توی Call Stack) که تابع فعلی رو فراخوانی کرده میدید، تا اون بتونه این خطا رو Handle کنه.

Exception اصلا یعنی چی؟ یعنی اینکه "اتفاق بدی رخ داده". توی CLR، هر Exception ای یک تایپی داره، اما این تایپ کجا معنا پیدا میکنه؟ این تایپ توی context ای که خطا رخ داده معنی پیدا میکنه. هر چه از خطا دورتر بشیم و اجازه بدیم Exception توی Call Stack بالا بره، در واقع داریم روی این "اتفاق بد" سرپوش میذاریم تا جاییکه اگر برنامه ما Exception مزبور رو Handle نکنه، ویندوز دادش در میاد و CLR Process ما رو terminate میکنه. چون ویندوز دیگه هیچ ایده ای نداره که این "اتفاق بد" چی بوده، ارسال یک پارامتر منفی به یک تابع ساده، یا نوشتن توی فلان سکتور از Hard Disc. در صورتیکه وقتی به منبع تولید کننده خطا نزدیک میشیم، این خطا معنای بیشتری پیدا میکنه و در نهایت، متوجه میشیم که فرضا پارامتر ورودی یک متود، حتما باید عدد مثبتی باشه، در صورتیکه چون منفی بوده و ما این Exception رو در جایگاه خودش Handle نکرده بودیم، CLR Process ما براحتی terminate شده و حالا باید جوابگوی کاربر عصبانی ای باشیم که پشت تلفن داره به رئیسمون شکایت میکنه!

بنابراین، بهتره که خطا رو نزدیک به منبع تولید کننده خطا رفع و رجوع کنیم و اجازه ندیم تا خطا به سطوح بالایی برنامه برسه.

اما این کد مشکل دیگه ای داره، که خیلی بدتر از نادیده گرفتن "بهترین تجارب و الگوها" هستش. این ایراد چی هستش؟ برای اینکه متوجه این مساله بشیم، ابتدا باید اندکی بیشتر در مورد Exception ها توضیح بدم. وقتی برنامه Exception ای Throw میکنه، توابع موجود در Call Stack به ترتیب این فرصت رو دارن که خطا رو بگیرن (بهش میگن Exception unwind) و بهش واکنش نشون بدن. اما وقتی برنامه ای اینکارو نمیکنه، خطا به سیستم عامل میرسه و سیستم عامل متوجه میشه که "اتفاق بدی توی فلان Process رخ داده". ما به این خطا ها میگیم، Unhandled Exception.

وقتی ویندوز با یک Unhandled Exception مواجه میشه، دیگه ایده ای در مورد اینکه چه اتفاق بدی باعث تولید این Exception شده، نداره. پس چی کار میکنه؟ برای اینکه از داده های نوشته شده توسط Process ما (مثل فایلهایی که برنامه ایجاد کرده، setting هایی که تو registery نوشته و ...) محافظت کنه، همون لحظه برنامه رو میبنده. ویندوز پیش خودش میگه "من که نمیدونم چه خطایی رخ داده. اگر الان بذارم این برنامه به کارش ادامه بده، ممکنه این خطا باعث بشه که بخشی از Registery رو بپرونه، اطلاعات اشتباه روی هارد دیسک بنویسه و خلاصه، صدمه ای جبران ناپذیر به اطلاعات برسه و این صدمه، بیشتر از اونی باشه که مورد انتظار کاربر و برنامه نویس بوده. پس بهترین کار اینه که اجرای برنامه رو پایان بدم تا اطلاعات فعلی دست نخورده باقی بمونه."

اینکه ما میتونیم Exception رو دور از جایی که رخ داده بگیریم، باعث ایجاد یک مشکل جانبی میشه. این مشکل چیه؟ thread برنامه ای که Exception رو داره میگیره اطلاع نداره که Exception کجا تولید شده، داخل خود برنامه، یا خارج از برنامه! بله. درست شنیدید. خارج از برنامه!

ویندوز، thread های برنامه رو توسط SEH از Exception هایی که در سیستم عامل رخ میدن، مطلع میکنه. فرض کنید توی کدتون، بخش Unmanged ای دارید که داره به اشتباه به حافظه ای که به اون تعلق نداره، دسترسی پیدا میکنه. این دسترسی، باعث تولید Access Violation میشه و AV یکی از Exception های سیستم عامل هست. وقتی این خطا رخ میده، CLR runtime خطا رو به دست برنامه شما میرسونه. شما هم که تو کدتون زدید catch (exception ex)، یعنی هر چی exception رخ دادش، بگیر... از جمله همین AV رو...

حالا تصور کنید چه اتفاق وحشتناکی داره میفته. کد شما، AV تولید کرده و شما دارید با گرفتن تمام exception ها، روی این مساله سرپوش میذارید. پس برنامه به کار خودش ادامه میده، یعنی به بلاک finally میره (در صورت وجود) و سپس به خط بعدی کد میره....... شما دستکاری مهلکی تو حافظه داشته اید و هنوز برنامه کار خودش رو ادامه میده. از این لحظه به بعد دیگه کل سیستم در معرض تهدیدی جدی هستش. ممکنه شما اقدام به نوشتن فایلی کنید، و اون فایل، بخاطر خطایی که روش سرپوش گذاشتید، overwrite بشه و ... (خودتون هر چیز بدی رو که مایل بودید، تصور کنید).

اما نگران نباشید. مایکروسافت تو نسخه بعدی .NET یعنی 4، این مشکل رو با معرفی CSE ها، رفع کرده. در واقع دیگه Exception های OS به دست برنامه شما نمیرسه، مگه اینکه Explicitly خودتون این تقاضا رو داشته باشید. برای اطلاعات بیشتر، می تونید این مقاله رو بخونید (http://msdn.microsoft.com/en-us/magazine/dd419661.aspx). برای اینکه با SEH آشنا بشید، میتونید این مقاله رو بخونید (http://www.microsoft.com/msj/0197/exception/exception.aspx).

نتیجه: اگر از .NET 4 به بعد استفاده میکنید، جای نگرانی وجود نداره، اگر چه گرفتن کلیه خطاها سرپوش گذاشتن رو وقایعی هستش که شما توان تعامل با اون رو توی اون فاز بخصوص از کد نداشته اید. اگر نمیتونید یا قرار نیست با exception ای که میگیرید، کاری کنید، بهتره اونو اصلا نگیرید و اجازه بدید توی callstack unwinding خودش مرحله به مرحله بالا بیاد. اگر میتونید توی اون فاز با exception خاصی تعامل داشته باشید، پس اونو بگیرید و اینکارو انجام بدید. اگر از .NET 4 به قبل استفاده میکنید، همواره حواستون باشه، که ممکنه exception ای از خارج بدست thread شما رسیده باشه و ادامه برنامه توی این شرایط، مطلقا، مطلقا کار صحیحی نیست.

موفق باشید.

ehsanxxx
دوشنبه 01 شهریور 1395, 21:43 عصر
دوستان فقط یادتون نره اگر از Catch و خطا در اون استفاده کردید حتمن از خاصیت message اون رو هم استفاده کنید تا از توضیح خطای بوجود اومده مطلع بشید. برای ادامه :
http://www.projectpardaz.ir/دستور-try-catch/ ‎

Maziar47
دوشنبه 01 شهریور 1395, 22:23 عصر
شما داخل بلوک Try یه کد رو میزارید اگر وقتی که برنامه در حال اجرا بود و کد های داخل بلوک Try دچار خطای زمان اجرا شدن دستورات داخل بلوک catch اجرا میشه و اگرم از بلوک finally استفاده کردی وقتی دستورات داخل بلوک catch یا Try اجرا شدن کدخای داخل بلوک finally اجرا میشن