بیان try-catch شامل یک بلوک try و یک یا بیش از یک جمله catch که بعد از آن بلوک می آید، مدیریت کننده هایی را برای خطاهای مختلف تعیین می کند. وقتی یک خطا پرتاب (throw) می شود (اتفاق می افتد/خودمان عمدا آن خطا را تولید می کنیم)، زبان عمومی زمان اجرا (CLR - Common Language Runtime) به دنبال بیان catch ی می گردد که آن خطا را مدیریت می کند می گردد. اگر متدی که فعلا" در حال اجرا است چنین بلوک catch ی نداشته باشد، CLR به متدی که این متد فعلی را فراخوانی کرده نگاه می کند و همینطور استک را به سمت بالا بازرسی می کند (تا به بلوک catch مربوطه برسد). اگر هیچ بلوک catch ی پیدا نشد، آنگاه CLR یک پیام خطای-مدیریت-نشده به کاربر نشان می دهد و روند اجرای برنامه را متوقف می کند.
بلوک try حاوی کد محافظت شده است ولی ممکن است خطا برایش اتفاق بیفتد. بلوک به اجرا ادامه می دهد زمانی که خطایی پرتاب شود یا بلوک با موفقیت کامل شود. برای مثال، تلاش زیر برای قالبریزی یک شیئ null ، خطای NullReferenceExeption را برپا می کند:
object o2 = null; try { int i2 = (int)o2; // Error }
هرچند جمله catch می تواند برای اینکه هر خطایی را بگیرد، بدون هیچ آرگومانی استفاده شود، اما این روش استفاده ، توصیه نمی شود. در کل، شما می بایست فقط آن خطاهایی را که می دانید چطور آنها را بهبود بخشید را catch کنید. بنابراین، شما می باید همیشه یک آرگومان که شئی ای مشتق شده از System.Exception را تعیین کنید. برای نمونه:
catch (InvalidCastException e) { }
به کار بردن بیش از یک جمله catch خاص در یک بیان try-catch امکان پذیر است. در چنین موردی، ترتیب جملات catch مهم است، زیرا جملات catch به ترتیب امتحان می شوند. خطاهای بارز تر و مشخص تر را قبل از خطاهایی که کمتر اتفاق می افتند catch کنید. اگر بلوک های catch را طوری مرتب کنید که به بلوکی از بلوک های آخر دسترسی نباشد، کامپایلر خطایی را تولید خواهد کرد.
در بلوک catch می توان از بیان throw ، برای دوباره پرتاب کردن یک استثناء، که توسط بیان catch گرفتار شده، استفاده نمود. مثلا" :
catch (InvalidCastException e) { throw (e); // Rethrowing exception e }
شما همچنین می توانید یک خطای جدید را throw (پرتاب) کنید. وقتی چنین کاری کردید، خطایی را که به عنوان خطای داخلی catch کرده اید را مشخص کنید.
catch (InvalidCastException e) { // Can do cleanup work here. throw new CustomException("Error message here.", e); }
اگر می خواهید خطایی که فعلا" توسط یک جمله بدون پارامتر catch مدیریت شده را دوباره پرتاب کنید، از بیان throw بدون آرگومان استفاده کنید. برای مثال:
catch { throw; }
وقتی داخل بلوک try هستید، فقط متغیرهایی که در آنجا اعلان شده اند را مقداردهی اولیه کنید؛ در غیر اینصورت، قبل از اجرای بلوک به پایان برسد، خطایی می تواند اتفاق بیافتد. برای مثال، در کد زیر، متغیر x در داخل بلوک try مقداردهی اولیه شده. تلاش برای استفاده از این متغیر از بیرون بلوک try در بیان (Write(x یک خطای کامپایلری تولید خواهد کرد.
static void Main() { int x; try { // Don't initialize this variable here. x = 123; } catch { } // Error: Use of unassigned local variable 'x'. Console.Write(x); }
مثال
در این مثال، بلوک try حاوی یک فراخوانی متد ProcessString است که ممکن است باعث ایجاد خطا شود. جمله catch شامل مدیر خطایی است که فقط یک پیام را روی صفحه نشان می دهد. وقتی بیان throw از داخل متد MyMethod فراخوانی شود، سیستم به دنبال بیان catch گشته و پیام Exception caught را نمایش می دهد.
class TryFinallyTest { static void ProcessString(string s) { if (s == null) { throw new ArgumentNullException(); } } static void Main() { string s = null; // For demonstration purposes. try { ProcessString(s); } catch (Exception e) { Console.WriteLine("{0} Exception caught.", e); } } } /* Output: System.ArgumentNullException: Value cannot be null. at TryFinallyTest.Main() Exception caught. * */
در این مثال، دو بیان catch استفاده شده. خطای مشخص تر، که اول آمده، گرفتار شده است.
class ThrowTest3 { static void ProcessString(string s) { if (s == null) { throw new ArgumentNullException(); } } static void Main() { try { string s = null; ProcessString(s); } // Most specific: catch (ArgumentNullException e) { Console.WriteLine("{0} First exception caught.", e); } // Least specific: catch (Exception e) { Console.WriteLine("{0} Second exception caught.", e); } } } /* Output: System.ArgumentNullException: Value cannot be null. at TryFinallyTest.Main() First exception caught. */
در مثال قبل، اگر با جمله catch ی که دارای حداقل درجه مشخص بودن است، شروع کنید، پیغام خطای زیر را خواهید گرفت:
A previous catch clause already catches all exceptions of this or a super type ('System.Exception')
به هر حال، برای catch کردن استثنا های با اولویت کمتر، بیان throw را با بیان زیر جایگزین کنید:
throw new Exception();