{"id":233,"date":"2014-08-15T07:00:00","date_gmt":"2014-08-15T07:00:00","guid":{"rendered":"https:\/\/blogs.msdn.microsoft.com\/oldnewthing\/2014\/08\/15\/the-scope-of-the-c-checkedunchecked-keyword-is-static-not-dynamic\/"},"modified":"2014-08-15T07:00:00","modified_gmt":"2014-08-15T07:00:00","slug":"the-scope-of-the-c-checkedunchecked-keyword-is-static-not-dynamic","status":"publish","type":"post","link":"https:\/\/devblogs.microsoft.com\/oldnewthing\/20140815-00\/?p=233","title":{"rendered":"The scope of the C# checked\/unchecked keyword is static, not dynamic"},"content":{"rendered":"<p>\nC# has operators <code>checked<\/code> and <code>unchecked<\/code>\nto control the behavior of the language in the face of integer overflow.\nThere are also <code>checked<\/code> and <code>unchecked<\/code> statements\nwhich apply the behavior to blocks of statements rather than single\nexpressions.\n<\/p>\n<pre>\nint x;\nx = checked(a + b); \/\/ evaluate with overflow checking\ny = unchecked(a + b); \/\/ evaluate without overflow checking\nchecked {\n x = a + b; \/\/ evaluate with overflow checking\n}\nunchecked {\n x = a + b; \/\/ evaluate without overflow checking\n}\n<\/pre>\n<p>\nWhy, then, doesn&#8217;t this code below raise an overflow exception?\n<\/p>\n<pre>\nclass Program {\n static int Multiply(int a, int b) { return a * b; }\n static int Overflow() { return Multiply(int.MaxValue, 2); }\n public static void Main() {\n  System.Console.WriteLine(checked(Overflow()));\n  checked {\n    System.Console.WriteLine(Overflow());\n  }\n }\n}\n<\/pre>\n<p>\n(Mini-exercise: Why couldn&#8217;t I have just written\n<code>static int Overflow() { return int.MaxValue * 2; }<\/code>?)\n<\/p>\n<p>\nThe answer is that the scope of the <code>checked<\/code> or\n<code>unchecked<\/code> keyword is static, not dynamic.\nWhether a particular arithmetic is checked or unchecked is\ndetermined at compile time, not at run time.\nSince the multiplication in the <code>Multiply<\/code> function\nis not explicitly marked checked or unchecked,\nuses the overflow context implied by your compiler options.\nAssuming you&#8217;ve left it at the default of\n<code>unchecked<\/code>,\nthis means that\nthere is no overflow checking in the <code>Multiply<\/code> function,\neven if you call it from a checked context.\nBecause once you call the <code>Multiply<\/code> function,\nyou have left the checked context.\n<\/p>\n<p>\nThe C# language specification addresses this issue not once,\nnot twice, but three times!\n(But it seems that some people miss it,\npossibly because there is\n<a HREF=\"http:\/\/blogs.msdn.com\/b\/oldnewthing\/archive\/2013\/04\/10\/10409822.aspx\">\ntoo much documentation<\/a>.)\n<\/p>\n<p>\nFirst, there is an\n<a HREF=\"http:\/\/msdn.microsoft.com\/en-us\/library\/aa691349(v=VS.71).aspx\">\nexplicit list<\/a> of\noperations which\nare controlled by the <code>checked<\/code> or <code>unchecked<\/code>\nkeyword:\n<\/p>\n<blockquote CLASS=\"q\">\n<ul>\n<li>The predefined <code>++<\/code> and <code>--<\/code> unary operators,\n    when the operand is of an integral type.<\/p>\n<li>The predefined <code>-<\/code> unary operator,\n    when the operand is of an integral type.<\/p>\n<li>The predefined <code>+<\/code>, <code>-<\/code>,\n    <code>*<\/code>, and <code>\/<\/code> binary operators,\n    when both operands are of integral types.<\/p>\n<li>Explicit numeric conversions from one integral type to another\n    integral type, or from <code>float<\/code> or <code>double<\/code>\n    to an integral type.\n<\/ul>\n<\/blockquote>\n<p>\nThat&#8217;s all.\nNote that function calls are not on the list.\n<\/p>\n<p>\nNow, that may have been a bit too subtle (documentation by omission),\nso the language specific goes ahead and calls it out.\n<\/p>\n<blockquote CLASS=\"q\">\n<p>\nThe <code>checked<\/code> and <code>unchecked<\/code> operators\nonly affect the overflow checking context for those operations\nthat are textually contained within the &#8220;<code>(<\/code>&#8221;\nand &#8220;<code>)<\/code>&#8221; tokens.\nThe operators have no effect on function members\nthat are invoked as a result of evaluating the contained expression.\n<\/p>\n<\/blockquote>\n<p>\nAnd then, in case you still didn&#8217;t get it, the language specification\neven includes an example:\n<\/p>\n<blockquote CLASS=\"q\">\n<pre>\nclass Test\n{\n   static int Multiply(int x, int y) {\n      return x * y;\n   }\n   static int F() {\n      return checked(Multiply(1000000, 1000000));\n   }\n}\n<\/pre>\n<p>\nThe use of <code>checked<\/code> in <code>F<\/code> does not\naffect the evaluation of <code>x * y<\/code> in\n<code>Multiply<\/code>,\nso <code>x * y<\/code> is evaluated in the default overflow\nchecking context.\n<\/p>\n<\/blockquote>\n<p>\n(I wrote my example before consulting the language specification.\nThat we both chose to use multiplication overflow is just a coincidence.)\n<\/p>\n<p>\nEven though the language specification\n<a HREF=\"http:\/\/www.theotherpages.org\/poems\/carrol03.html\">\nsays it three times<\/a>,\nin three different ways,\nthere are still people who are under the mistaken impression that\nthe scope of the <code>checked<\/code> keyword is dynamic.\n<\/p>\n<p>\nAnother thing you may have notice is that the <code>checked<\/code>\nand <code>unchecked<\/code> keywords apply only to the built-in\narithmetic operations on integers.\nThey do not apply to overloaded operators or to operators on custom\nclasses.\n<\/p>\n<p>\nWhich makes sense if you think about it,\nbecause in order to define an overloaded operator or an operator\non a custom class,\nyou need to write the implementation as a separate function,\nin which case you have already left the scope of the\n<code>checked<\/code> and <code>unchecked<\/code> keywords.\n<\/p>\n<p>\nAnd now we are leaving the scope of CLR Week.\nYou can remove your hands from your ears now.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>C# has operators checked and unchecked to control the behavior of the language in the face of integer overflow. There are also checked and unchecked statements which apply the behavior to blocks of statements rather than single expressions. int x; x = checked(a + b); \/\/ evaluate with overflow checking y = unchecked(a + b); [&hellip;]<\/p>\n","protected":false},"author":1069,"featured_media":111744,"comment_status":"open","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"_acf_changed":false,"footnotes":""},"categories":[1],"tags":[25],"class_list":["post-233","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-oldnewthing","tag-code"],"acf":[],"blog_post_summary":"<p>C# has operators checked and unchecked to control the behavior of the language in the face of integer overflow. There are also checked and unchecked statements which apply the behavior to blocks of statements rather than single expressions. int x; x = checked(a + b); \/\/ evaluate with overflow checking y = unchecked(a + b); [&hellip;]<\/p>\n","_links":{"self":[{"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/posts\/233","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/users\/1069"}],"replies":[{"embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/comments?post=233"}],"version-history":[{"count":0,"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/posts\/233\/revisions"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/media\/111744"}],"wp:attachment":[{"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/media?parent=233"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/categories?post=233"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/tags?post=233"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}