{"id":1933,"date":"2009-02-19T17:41:00","date_gmt":"2009-02-19T17:41:00","guid":{"rendered":"https:\/\/blogs.msdn.microsoft.com\/dotnet\/2009\/02\/19\/why-catchexceptionempty-catch-is-bad\/"},"modified":"2021-10-04T16:06:28","modified_gmt":"2021-10-04T23:06:28","slug":"why-catchexceptionempty-catch-is-bad","status":"publish","type":"post","link":"https:\/\/devblogs.microsoft.com\/dotnet\/why-catchexceptionempty-catch-is-bad\/","title":{"rendered":"Why catch(Exception)\/empty catch is bad"},"content":{"rendered":"<p class=\"MsoNormal\"><span><font size=\"3\" face=\"Calibri\">&nbsp;<\/font><\/p>\n<p><\/span><span><\/p>\n<p><font size=\"3\" face=\"Calibri\">&nbsp;<\/font><\/p>\n<p><\/span><\/p>\n<p class=\"MsoNormal\"><span><font size=\"3\" face=\"Calibri\">You&rsquo;ve seen the advice before&mdash;<\/font><\/span><a href=\"http:\/\/blogs.msdn.com\/kcwalina\/archive\/2006\/07\/05\/657268.aspx\"><font color=\"#0000ff\" size=\"3\" face=\"Calibri\">it&rsquo;s not a good programming practice to catch System.Exception<\/font><\/a><span><font size=\"3\"><font face=\"Calibri\">. Because managed exceptions are hierarchical, catching the top of the hierarchy&mdash;e.g., catch(Exception)&mdash;is an easy way to make sure that you catch all exceptions. <span>&nbsp;<\/span>But do you really want to catch all exceptions? <\/p>\n<p><\/font><\/font><\/span><\/p>\n<p class=\"MsoNormal\"><span><\/p>\n<p><font size=\"3\" face=\"Calibri\">&nbsp;<\/font><\/p>\n<p><\/span><\/p>\n<p class=\"MsoNormal\"><span><font size=\"3\"><font face=\"Calibri\">Empty catch statements can be just as bad, depending on the MSIL code that your language generates. C# turns an empty catch statement into catch(System.Object) which means you end up catching all exceptions&mdash;even non-CLS compliant exceptions. VB is better-behaved, turning an empty catch statement into <i>catch e as System.Exception<\/i> which limits you to catching CLS compliant exceptions.<\/p>\n<p><\/font><\/font><\/span><\/p>\n<p class=\"MsoNormal\"><span><\/p>\n<p><font size=\"3\" face=\"Calibri\">&nbsp;<\/font><\/p>\n<p><\/span><\/p>\n<p class=\"MsoNormal\"><span><font size=\"3\"><font face=\"Calibri\">Instead, you should catch the exact exception types that you expect because these are the types your code is prepared to handle. Obviously, any code that throws an exception is a good candidate for corresponding catch. MSDN documents all exceptions that can be raised from BCL functions. For example, System.IO.StreamReader () can throw ArgumentException or ArgumentNullException. If you use a StreamReader you should catch&mdash;and handle&mdash;these two exceptions.<i><\/p>\n<p><\/i><\/font><\/font><\/span><\/p>\n<p class=\"MsoNormal\"><span><\/p>\n<p><font size=\"3\" face=\"Calibri\">&nbsp;<\/font><\/p>\n<p><\/span><\/p>\n<p class=\"MsoNormal\"><span><font size=\"3\" face=\"Calibri\">We sometimes see advice that suggests you should catch all exceptions. In <\/font><\/span><a href=\"http:\/\/blogs.msdn.com\/eric_brechner\/archive\/2008\/05\/01\/crash-dummies-resilience.aspx\"><font color=\"#0000ff\" size=\"3\" face=\"Calibri\">Eric Brechner&rsquo;s Hard Code<\/font><\/a><span><font size=\"3\" face=\"Calibri\"> column he said that letting an application crash and invoke <\/font><\/span><a href=\"http:\/\/msdn.microsoft.com\/en-us\/isv\/bb190483.aspx\"><font color=\"#0000ff\" size=\"3\" face=\"Calibri\">Windows Error Reporting<\/font><\/a><span><font size=\"3\"><font face=\"Calibri\"> (commonly called &ldquo;Watson&rdquo; from the pre-Vista days) was &ldquo;completely idiotic and irresponsible.&rdquo; He suggests that instead you catch all exceptions and &ldquo;try to correct&rdquo; them. <\/p>\n<p><\/font><\/font><\/span><\/p>\n<p class=\"MsoNormal\"><span><\/p>\n<p><font size=\"3\" face=\"Calibri\">&nbsp;<\/font><\/p>\n<p><\/span><\/p>\n<p class=\"MsoNormal\"><span><font size=\"3\"><font face=\"Calibri\">There&rsquo;s one small problem with Eric&rsquo;s advice: the word &ldquo;try&rdquo;. When you catch an exception you MUST handle the exceptional condition. Catching an exception is a statement that you can handle the exception and restore the program to a non-exceptional state. Trying to handle an exception isn&rsquo;t sufficient. Follow the advice of someone older and wiser:&nbsp;&ldquo;Do, or do not. There is no &lsquo;try&rsquo;.&rdquo;<\/p>\n<p><\/font><\/font><\/span><\/p>\n<p class=\"MsoNormal\"><span><\/p>\n<p><font size=\"3\" face=\"Calibri\">&nbsp;<\/font><\/p>\n<p><\/span><\/p>\n<p class=\"MsoNormal\"><span><font size=\"3\" face=\"Calibri\">One key problem is that our exception hierarchy is a single mechanism representing multiple exceptional conditions. <\/font><\/span><a href=\"http:\/\/blogs.msdn.com\/kcwalina\/archive\/2007\/01\/30\/ExceptionHierarchies.aspx\"><font color=\"#0000ff\" size=\"3\" face=\"Calibri\">Krzysztof Cwalina explains this pretty well<\/font><\/a><span><font size=\"3\"><font face=\"Calibri\">, breaking exceptional conditions into three sets: usage errors, logical errors and system failures. Usage errors are a condition that should always be fixed by the developer&mdash;for example, if an API cannot take null, the developer should ensure that she doesn&rsquo;t pass in null. Logical errors can&rsquo;t be detected at development time but should be handled at program runtime by the program itself. For example, a FileNotFoundException should be handled by creating the file or prompting the user for a new filename. System failures, however, cannot be handled by code. System failures indicate that something has gone wrong outside of your program&rsquo;s scope. Your program can not be expected to correct a system failure. Thus the suggestion that you &ldquo;try to correct&rdquo; the error condition cannot reasonably be applied to system failures. <\/p>\n<p><\/font><\/font><\/span><\/p>\n<p class=\"MsoNormal\"><span><\/p>\n<p><font size=\"3\" face=\"Calibri\">&nbsp;<\/font><\/p>\n<p><\/span><\/p>\n<p class=\"MsoNormal\"><span><font size=\"3\"><font face=\"Calibri\">Let&rsquo;s say your program causes an access violation and you catch the AccessViolationException. What can you do now? Find the pointer which has the bad value and set it to point to the right memory? If you could do that, you wouldn&rsquo;t have AV&rsquo;d in the first place. Catching the exception is the wrong thing to do if you can&rsquo;t correct the error. In the case of a system failure you can&rsquo;t correct the error.<\/p>\n<p><\/font><\/font><\/span><\/p>\n<p class=\"MsoNormal\"><span><\/p>\n<p><font size=\"3\" face=\"Calibri\">&nbsp;<\/font><\/p>\n<p><\/span><\/p>\n<p class=\"MsoNormal\"><span><font size=\"3\" face=\"Calibri\">We&rsquo;re making a change in Visual Studio 2010&rsquo;s CLR to make it harder to make this mistake. When an exception could indicate a corrupted process state&mdash;what Krzysztof calls a system failure&mdash;you&rsquo;ll have to use a new attribute to indicate your intention explicitly. You can read about the details in the <\/font><\/span><a href=\"http:\/\/msdn.microsoft.com\/en-us\/magazine\/dd419661.aspx\"><font color=\"#0000ff\" size=\"3\" face=\"Calibri\">CLR Inside Out column<\/font><\/a><span><font size=\"3\"><font face=\"Calibri\"> in February&rsquo;s MSDN Magazine. Even with our Corrupted State Exceptions work, catching all exceptions is not a good idea. If you can&rsquo;t correct the condition that resulted in an exception being raised you&rsquo;re always much better off Watsoning up (that is, letting your program exit and invoke Windows Error Reporting.) Watson will report back from the user&rsquo;s machine so that you can fix the error in your next servicing or release. <\/p>\n<p><\/font><\/font><\/span><\/p>\n<p class=\"MsoNormal\"><span><\/p>\n<p><font size=\"3\" face=\"Calibri\">&nbsp;<\/font><\/p>\n<p><\/span><\/p>\n<p class=\"MsoNormal\"><span><\/p>\n<p><font size=\"3\" face=\"Calibri\">&nbsp;<\/font><\/p>\n<p><\/span><\/p>\n<p class=\"MsoNormal\"><span><\/p>\n<p><font size=\"3\" face=\"Calibri\">Andrew Pardoe<\/font><\/p>\n<p><\/span><\/p>\n<p class=\"MsoNormal\"><span><\/p>\n<p><font size=\"3\" face=\"Calibri\">Program Manager, CLR<\/font><\/p>\n<p><\/span><\/p>\n<p class=\"MsoNormal\"><span><\/p>\n<p><font size=\"3\" face=\"Calibri\"><\/font><\/p>\n<p><\/span>&nbsp;<\/p>\n","protected":false},"excerpt":{"rendered":"<p>&nbsp; &nbsp; You&rsquo;ve seen the advice before&mdash;it&rsquo;s not a good programming practice to catch System.Exception. Because managed exceptions are hierarchical, catching the top of the hierarchy&mdash;e.g., catch(Exception)&mdash;is an easy way to make sure that you catch all exceptions. &nbsp;But do you really want to catch all exceptions? &nbsp; Empty catch statements can be just as [&hellip;]<\/p>\n","protected":false},"author":342,"featured_media":58792,"comment_status":"open","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"_acf_changed":false,"footnotes":""},"categories":[685],"tags":[],"class_list":["post-1933","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-dotnet"],"acf":[],"blog_post_summary":"<p>&nbsp; &nbsp; You&rsquo;ve seen the advice before&mdash;it&rsquo;s not a good programming practice to catch System.Exception. Because managed exceptions are hierarchical, catching the top of the hierarchy&mdash;e.g., catch(Exception)&mdash;is an easy way to make sure that you catch all exceptions. &nbsp;But do you really want to catch all exceptions? &nbsp; Empty catch statements can be just as [&hellip;]<\/p>\n","_links":{"self":[{"href":"https:\/\/devblogs.microsoft.com\/dotnet\/wp-json\/wp\/v2\/posts\/1933","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/devblogs.microsoft.com\/dotnet\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/devblogs.microsoft.com\/dotnet\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/dotnet\/wp-json\/wp\/v2\/users\/342"}],"replies":[{"embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/dotnet\/wp-json\/wp\/v2\/comments?post=1933"}],"version-history":[{"count":0,"href":"https:\/\/devblogs.microsoft.com\/dotnet\/wp-json\/wp\/v2\/posts\/1933\/revisions"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/dotnet\/wp-json\/wp\/v2\/media\/58792"}],"wp:attachment":[{"href":"https:\/\/devblogs.microsoft.com\/dotnet\/wp-json\/wp\/v2\/media?parent=1933"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/dotnet\/wp-json\/wp\/v2\/categories?post=1933"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/dotnet\/wp-json\/wp\/v2\/tags?post=1933"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}