<?xml version="1.0" encoding="UTF-8" ?>
<?xml-stylesheet type="text/xsl" href="http://blogs.msdn.com/utility/FeedStylesheets/rss.xsl" media="screen"?><rss version="2.0" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:slash="http://purl.org/rss/1.0/modules/slash/" xmlns:wfw="http://wellformedweb.org/CommentAPI/"><channel><title>Sam Ng's Blog : Lambda Expressions</title><link>http://blogs.msdn.com/samng/archive/tags/Lambda+Expressions/default.aspx</link><description>Tags: Lambda Expressions</description><dc:language>en-US</dc:language><generator>CommunityServer 2.1 SP1 (Build: 61025.2)</generator><item><title>Compiler-generated scopes for local variable declarations</title><link>http://blogs.msdn.com/samng/archive/2007/11/07/compiler-generated-scopes-for-local-variable-declarations.aspx</link><pubDate>Wed, 07 Nov 2007 09:57:00 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:5952414</guid><dc:creator>samng</dc:creator><slash:comments>6</slash:comments><comments>http://blogs.msdn.com/samng/comments/5952414.aspx</comments><wfw:commentRss>http://blogs.msdn.com/samng/commentrss.aspx?PostID=5952414</wfw:commentRss><description>&lt;p&gt;I was tasked with understanding and fixing a bug on error reporting with foreach iteration variables the other day, and it got me thinking about local variable scoping rules in C# in general. First, the bug.  &lt;/p&gt;&lt;h1&gt;&lt;/h1&gt; &lt;h5&gt;The Bug&lt;/h5&gt; &lt;p&gt;Consider the following code:&lt;/p&gt;&lt;pre class="code"&gt;&lt;span style="color: rgb(0, 0, 255);"&gt;class&lt;/span&gt; &lt;span style="color: rgb(43, 145, 175);"&gt;C&lt;br&gt;&lt;/span&gt;{&lt;br&gt;    &lt;span style="color: rgb(0, 0, 255);"&gt;static&lt;/span&gt; &lt;span style="color: rgb(0, 0, 255);"&gt;void&lt;/span&gt; Main(&lt;span style="color: rgb(0, 0, 255);"&gt;string&lt;/span&gt;[] args)&lt;br&gt;    {&lt;br&gt;        &lt;span style="color: rgb(0, 0, 255);"&gt;foreach&lt;/span&gt; (&lt;span style="color: rgb(0, 0, 255);"&gt;int&lt;/span&gt; myCollection &lt;span style="color: rgb(0, 0, 255);"&gt;in&lt;/span&gt; myCollection)&lt;br&gt;        {&lt;br&gt;            &lt;span style="color: rgb(0, 128, 0);"&gt;// Your code here&lt;br&gt;&lt;/span&gt;        }&lt;br&gt;    }&lt;br&gt;}&lt;br&gt;&lt;/pre&gt;
&lt;p&gt;This code should clearly not compile, because myCollection is used before it is declared. But it does! On VS2008 Beta2, this code currently compiles, and on runtime, produces a TypeLoadException. 
&lt;/p&gt;&lt;h5&gt;What happened?&lt;/h5&gt;
&lt;p&gt;Well, first let us consider how a foreach statement is expanded. According to the C# language specification section 8.8.4, the foreach statement is expanded as follows:&lt;/p&gt;&lt;pre class="code"&gt;&lt;span style="color: rgb(43, 145, 175);"&gt;E&lt;/span&gt; enumerator = (collection).GetEnumerator();&lt;br&gt;&lt;span style="color: rgb(0, 0, 255);"&gt;try&lt;br&gt;&lt;/span&gt;{&lt;br&gt;    &lt;span style="color: rgb(0, 0, 255);"&gt;while&lt;/span&gt; (enumerator.MoveNext())&lt;br&gt;    {&lt;br&gt;        ElementType element = (ElementType)enumerator.Current;&lt;br&gt;        statement;&lt;br&gt;    }&lt;br&gt;}&lt;br&gt;&lt;span style="color: rgb(0, 0, 255);"&gt;finally&lt;br&gt;&lt;/span&gt;{&lt;br&gt;    &lt;span style="color: rgb(43, 145, 175);"&gt;IDisposable&lt;/span&gt; disposable = enumerator &lt;span style="color: rgb(0, 0, 255);"&gt;as&lt;/span&gt; System.&lt;span style="color: rgb(43, 145, 175);"&gt;IDisposable&lt;/span&gt;;&lt;br&gt;    &lt;span style="color: rgb(0, 0, 255);"&gt;if&lt;/span&gt; (disposable != &lt;span style="color: rgb(0, 0, 255);"&gt;null&lt;/span&gt;) disposable.Dispose();&lt;br&gt;}&lt;br&gt;&lt;/pre&gt;
&lt;p&gt;Notice that the call to "collection.GetEnumerator" happens outside of the try scope and the while scope, but the definition of the iteration variable "element" occurs inside the while scope. The bug was that when we attempted to bind the collection to get the GetEnumerator call off of it, we bound it inside the while scope instead of outside the try scope. As such, when we asked the local symbol table to resolve the name "myCollection", it returned us the iteration variable declared inside the while scope. This caused the compiler to incorrectly accept this program and not produce an error when compiling it. When one tries to run the program however, the CLR detects the problem with the type, and consequently throws the TypeLoadException, as expected. 
&lt;/p&gt;&lt;p&gt;The fix was simply to move the binding of the collection outside the try scope, and correctly report that "myCollection" is not defined in the outer scope. 
&lt;/p&gt;&lt;h5&gt;Scoping rules&lt;/h5&gt;
&lt;p&gt;That got me thinking about scoping rules in general. Where do we introduce local variables and scopes that may not be intuitive to the user? What exactly are our local variable scoping rules to begin with? 
&lt;/p&gt;&lt;p&gt;I'll deal with the latter (important!) question in a subsequent post. 
&lt;/p&gt;&lt;p&gt;In addition to variable declaration statements, the language provides four other mechanisms to declare local variables. 
&lt;/p&gt;&lt;ol&gt;
&lt;li&gt;Foreach iteration variables 
&lt;/li&gt;&lt;li&gt;Lambda parameters/Anonymous method parameters 
&lt;/li&gt;&lt;li&gt;Catch exception variables 
&lt;/li&gt;&lt;li&gt;Using statement variables&lt;/li&gt;&lt;/ol&gt;
&lt;p&gt;For those interested, I'll briefly describe how the remaining three mechanisms declare their locals, and how they are scoped. 
&lt;/p&gt;&lt;h5&gt;Lambda Parameters&lt;/h5&gt;
&lt;p&gt;Lambda parameters work as one would expect - the parameters are declared as local variables inside the scope of the body of the lambda. From section 7.14.1 of the C# language specification: 
&lt;/p&gt;&lt;h6&gt;The optional &lt;i&gt;anonymous-function-signature &lt;/i&gt;of an anonymous function defines the names and optionally the types of the formal parameters for the anonymous function. The scope of the parameters of the anonymous function is the &lt;i&gt;anonymous-function-body&lt;/i&gt;. (§3.7) Together with the parameter list (if given) the anonymous-method-body constitutes a declaration space (§3.3). It is thus a compile-time error for the name of a parameter of the anonymous function to match the name of a local variable, local constant or parameter whose scope includes the &lt;i&gt;anonymous-method-expression&lt;/i&gt; or &lt;i&gt;lambda-expression&lt;/i&gt;.&lt;/h6&gt;
&lt;p&gt;In essence, the last sentence in that statement says that you cannot declare a parameter of a lambda or anonymous method (I'll refer to the two simply as the lambda) which has the same name as any local variable in the scope of the lambda's declaration. Why? Because it would give a different meaning to the name inside the body of the lambda. I'll elaborate on this more in my next post. 
&lt;/p&gt;&lt;h5&gt;Catch Blocks&lt;/h5&gt;
&lt;p&gt;Catch blocks that declare local variables are scoped for the lifetime of the catch block: 
&lt;/p&gt;&lt;h6&gt;When a catch clause specifies both a &lt;i&gt;class-type&lt;/i&gt; and an &lt;i&gt;identifier&lt;/i&gt;, an &lt;i&gt;&lt;b&gt;exception variable&lt;/b&gt;&lt;/i&gt; of the given name and type is declared. The exception variable corresponds to a local variable with a scope that extends over the catch block. &lt;/h6&gt;
&lt;p&gt;Any exception variables declared in the catch block must have a type that is System.Exception, is derived from System.Exception, or is a type parameter that has System.Exception (or a subclass thereof) as its effective base class. 
&lt;/p&gt;&lt;h5&gt;Using Statements&lt;/h5&gt;
&lt;p&gt;Using statements work pretty much as expected as well:&lt;/p&gt;&lt;pre class="code"&gt;{&lt;br&gt;    &lt;span style="color: rgb(43, 145, 175);"&gt;ResourceType&lt;/span&gt; resource = expression;&lt;br&gt;    &lt;span style="color: rgb(0, 0, 255);"&gt;try&lt;br&gt;&lt;/span&gt;    {&lt;br&gt;        statement;&lt;br&gt;    }&lt;br&gt;    &lt;span style="color: rgb(0, 0, 255);"&gt;finally&lt;br&gt;&lt;/span&gt;    {&lt;br&gt;        &lt;span style="color: rgb(0, 0, 255);"&gt;if&lt;/span&gt; (resource != &lt;span style="color: rgb(0, 0, 255);"&gt;null&lt;/span&gt;) ((&lt;span style="color: rgb(43, 145, 175);"&gt;IDisposable&lt;/span&gt;)resource).Dispose();&lt;br&gt;    }&lt;br&gt;}&lt;/pre&gt;
&lt;p&gt;Note that for using statements, the local variable that is declared for the resource acquisition is read-only. It is a compile time error to attempt to modify any local variables declared in this manner. Note also that a using statement that acquires more than one resource is really syntactic sugar for nested using statements, and is bound as a series of nested try blocks. 
&lt;/p&gt;&lt;p&gt;Any resource acquisition variables must be of a type that implements System.IDisposable.&lt;/p&gt;&lt;a href="http://11011.net/software/vspaste" mce_href="http://11011.net/software/vspaste"&gt;&lt;/a&gt;&lt;a href="http://www.dotnetkicks.com/kick/?url=http%3a%2f%2fblogs.msdn.com%2fsamng%2farchive%2f2007%2f11%2f07%2fcompiler-generated-scopes-for-local-variable-declarations.aspx"&gt;&lt;img src="http://www.dotnetkicks.com/Services/Images/KickItImageGenerator.ashx?url=http%3a%2f%2fblogs.msdn.com%2fsamng%2farchive%2f2007%2f11%2f07%2fcompiler-generated-scopes-for-local-variable-declarations.aspx" alt="kick it on DotNetKicks.com" border="0"&gt;&lt;/a&gt;&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=5952414" width="1" height="1"&gt;</description><category domain="http://blogs.msdn.com/samng/archive/tags/Local+Variable+Scoping/default.aspx">Local Variable Scoping</category><category domain="http://blogs.msdn.com/samng/archive/tags/Using+Statements/default.aspx">Using Statements</category><category domain="http://blogs.msdn.com/samng/archive/tags/Lambda+Expressions/default.aspx">Lambda Expressions</category><category domain="http://blogs.msdn.com/samng/archive/tags/Foreach+Statements/default.aspx">Foreach Statements</category></item></channel></rss>