<?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 : Variable redeclaration</title><link>http://blogs.msdn.com/samng/archive/tags/Variable+redeclaration/default.aspx</link><description>Tags: Variable redeclaration</description><dc:language>en-US</dc:language><generator>CommunityServer 2.1 SP1 (Build: 61025.2)</generator><item><title>Local variable scoping in C#</title><link>http://blogs.msdn.com/samng/archive/2007/11/09/local-variable-scoping-in-c.aspx</link><pubDate>Fri, 09 Nov 2007 21:38:43 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:6024701</guid><dc:creator>samng</dc:creator><slash:comments>7</slash:comments><comments>http://blogs.msdn.com/samng/comments/6024701.aspx</comments><wfw:commentRss>http://blogs.msdn.com/samng/commentrss.aspx?PostID=6024701</wfw:commentRss><description>&lt;p&gt;In my previous post, &lt;a href="http://blogs.msdn.com/samng/archive/2007/11/07/compiler-generated-scopes-for-local-variable-declarations.aspx"&gt;Compiler-generated scopes for local variable declarations&lt;/a&gt;, I briefly touched on the issue of multiple meanings applied to the same name. In this post, I'll aim to flush out the compiler's rules with regards to binding names in their local scopes.&lt;/p&gt; &lt;h5&gt;&lt;/h5&gt; &lt;h5&gt;Simple name resolution&lt;/h5&gt; &lt;p&gt;First, lets recall the spec's definition of simple name resolution, from section 7.5.2:&lt;/p&gt; &lt;h6&gt;If [...] the &lt;em&gt;simple-name&lt;/em&gt; appears within a &lt;em&gt;block &lt;/em&gt;and if the &lt;em&gt;block&lt;/em&gt;’s (or an enclosing &lt;em&gt;block&lt;/em&gt;’s) local variable declaration space (§3.3) contains a local variable, parameter or constant with name I, then the &lt;em&gt;simple-name &lt;/em&gt;refers to that local variable, parameter or constant and is classified as a variable or value.&lt;/h6&gt; &lt;p&gt;Simply put, the simple name gets resolved to whatever is declared inside its current block, &lt;strong&gt;regardless of whether or not there already exists a declaration of the name outside of the block&lt;/strong&gt;. So consider the following:&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;/span&gt;{
    &lt;span style="color: rgb(0,0,255)"&gt;public&lt;/span&gt; &lt;span style="color: rgb(0,0,255)"&gt;int&lt;/span&gt; y;

    &lt;span style="color: rgb(0,0,255)"&gt;void&lt;/span&gt; Foo()
    {
        &lt;span style="color: rgb(0,0,255)"&gt;int&lt;/span&gt; x;
        x = 0; &lt;span style="color: rgb(0,128,0)"&gt;// (1) This binds to the local variable defined above.
&lt;/span&gt;        y = 0; &lt;span style="color: rgb(0,128,0)"&gt;// (2) This binds to the field y.

&lt;/span&gt;        {
            x = &lt;span style="color: rgb(163,21,21)"&gt;"s"&lt;/span&gt;; &lt;span style="color: rgb(0,128,0)"&gt;// (3) This binds to the local defined below.
&lt;/span&gt;            &lt;span style="color: rgb(0,0,255)"&gt;string&lt;/span&gt; x;

            y = &lt;span style="color: rgb(163,21,21)"&gt;"s"&lt;/span&gt;; &lt;span style="color: rgb(0,128,0)"&gt;// (4) This binds to the local defined below.
&lt;/span&gt;            &lt;span style="color: rgb(0,0,255)"&gt;string&lt;/span&gt; y;
        }
    }
}&lt;/pre&gt;&lt;a href="http://11011.net/software/vspaste"&gt;&lt;/a&gt;
&lt;p&gt;Notice that both (3) and (4) produce compiler errors, as well as the redeclarations of x and y on the lines following (3) and (4) respectively. This is in accordance with section 5.1.7 of the spec:&lt;/p&gt;
&lt;h6&gt;Within the scope of a local variable introduced by a &lt;em&gt;local-variable-declaration&lt;/em&gt;, it is a compile-time error to refer to that local variable in a textual position that precedes its &lt;em&gt;local-variable-declarator&lt;/em&gt;. If the local variable declaration is implicit (§8.5.1), it is also an error to refer to the variable within its &lt;em&gt;local-variable-declarator&lt;/em&gt;. &lt;/h6&gt;
&lt;h6&gt;Within the scope of a local variable, it is a compile-time error to refer to the local variable in a textual position that precedes the &lt;em&gt;local-variable-declarator &lt;/em&gt;of the local variable.&lt;/h6&gt;
&lt;h5&gt;Locals preceding their declarator&lt;/h5&gt;
&lt;p&gt;Lets unpack this. First, lets quickly note that it is an error to refer to a local variable in a textual position that &lt;em&gt;precedes &lt;/em&gt;its declarator. However, referring to it &lt;em&gt;inside&lt;/em&gt; its declarator is permitted if the local variable is not implicitly typed. That means that the following is true:&lt;/p&gt;&lt;pre class="code"&gt;&lt;span style="color: rgb(0,0,255)"&gt;    int&lt;/span&gt; t = (t = 5); &lt;span style="color: rgb(0,128,0)"&gt;// OK
&lt;/span&gt;    &lt;span style="color: rgb(0,0,255)"&gt;var&lt;/span&gt; s = (s = 10); &lt;span style="color: rgb(0,128,0)"&gt;// Error&lt;/span&gt;&lt;/pre&gt;&lt;a href="http://11011.net/software/vspaste"&gt;&lt;/a&gt;
&lt;p&gt;In the first statement, by the time we attempt to bind the right hand side of the assignment statement, we've already declared that t is of type int. We can then bind the right hand side successfully with that knowledge, and then bind the assignment to the left hand side variable, which is the variable initializer. However, in the second statement, we do not have a type for s initially, so when we bind the right hand side of the assignment, we cannot determine if 10 is assignable to s. Consider the following:&lt;pre class="code"&gt;&lt;span style="color: rgb(0,0,255)"&gt;    var&lt;/span&gt; t = (Foo() ? t = &lt;span style="color: rgb(163,21,21)"&gt;"test"&lt;/span&gt;: t = 15);&lt;/pre&gt;&lt;a href="http://11011.net/software/vspaste"&gt;&lt;/a&gt;
&lt;p&gt;What would t's type be? We cannot report convertibility errors on the right hand side for the two branches of the ternary because we don't have a type for t to report convertibility errors on. 
&lt;p&gt;We therefore decided simply to disallow this scenario by disallowing the usage of the local variable in its declarator. 
&lt;h5&gt;Name Hiding?&lt;/h5&gt;
&lt;p&gt;We should note that name hiding is only allowed on fields that have not been referenced in the current scope. For instance:&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;/span&gt;{
    &lt;span style="color: rgb(0,0,255)"&gt;int&lt;/span&gt; x;
    &lt;span style="color: rgb(0,0,255)"&gt;int&lt;/span&gt; r;
    &lt;span style="color: rgb(0,0,255)"&gt;void&lt;/span&gt; Foo(&lt;span style="color: rgb(0,0,255)"&gt;int&lt;/span&gt; y)
    {
        &lt;span style="color: rgb(0,0,255)"&gt;int&lt;/span&gt; z;
        &lt;span style="color: rgb(0,0,255)"&gt;int&lt;/span&gt; s;

        &lt;span style="color: rgb(0,128,0)"&gt;// Legal - x has not been used in this context yet.
&lt;/span&gt;        &lt;span style="color: rgb(0,0,255)"&gt;string&lt;/span&gt; x = &lt;span style="color: rgb(163,21,21)"&gt;"s"&lt;/span&gt;;

        &lt;span style="color: rgb(0,128,0)"&gt;// Illegal - cannot hide parameters.
&lt;/span&gt;        &lt;span style="color: rgb(0,0,255)"&gt;string&lt;/span&gt; y;

        &lt;span style="color: rgb(0,128,0)"&gt;// Illegal - cannot declare two locals of the same 
&lt;/span&gt;        &lt;span style="color: rgb(0,128,0)"&gt;// name in the same scope.
&lt;/span&gt;        &lt;span style="color: rgb(0,0,255)"&gt;string&lt;/span&gt; z;

        r = 10;
        {
            &lt;span style="color: rgb(0,128,0)"&gt;// Illegal - r has already been used in the parent 
&lt;/span&gt;            &lt;span style="color: rgb(0,128,0)"&gt;// scope, so cannot redefine it.
&lt;/span&gt;            &lt;span style="color: rgb(0,0,255)"&gt;string&lt;/span&gt; r = &lt;span style="color: rgb(163,21,21)"&gt;"s"&lt;/span&gt;;

            &lt;span style="color: rgb(0,128,0)"&gt;// Illegal - cannot hide locals.
&lt;/span&gt;            &lt;span style="color: rgb(0,0,255)"&gt;string&lt;/span&gt; s = &lt;span style="color: rgb(163,21,21)"&gt;"s"&lt;/span&gt;;
        }
    }
}&lt;/pre&gt;&lt;a href="http://11011.net/software/vspaste"&gt;&lt;a href="http://11011.net/software/vspaste"&gt;&lt;/a&gt;
&lt;p&gt;Notice that the only legal hiding action is the first one - you are allowed to redefine x to be a string, because it has not been referenced as a field in any containing scope for the method Foo.&lt;/p&gt;
&lt;h5&gt;When is it an error? &lt;/h5&gt;
&lt;p&gt;As you can imagine, this notion of using a name before its declarator will cause the compiler to generate some errors when the situation occurs. Let me first outline the different situations that this can occur, and give quick examples.&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;/span&gt;{
    &lt;span style="color: rgb(0,0,255)"&gt;int&lt;/span&gt; x;
    &lt;span style="color: rgb(0,0,255)"&gt;int&lt;/span&gt; y;
    &lt;span style="color: rgb(0,0,255)"&gt;int&lt;/span&gt; z;
    &lt;span style="color: rgb(0,0,255)"&gt;void&lt;/span&gt; Foo()
    {
        x = 10; &lt;span style="color: rgb(0,128,0)"&gt;// (1) Binds to C.x
&lt;/span&gt;        {
            &lt;span style="color: rgb(0,128,0)"&gt;// (2) Binds to local variable declared below. 
&lt;/span&gt;            &lt;span style="color: rgb(0,128,0)"&gt;// Error - usage before declaration.
&lt;/span&gt;            x = 10;

            &lt;span style="color: rgb(0,128,0)"&gt;// (3) Error, cannot redefine x because x has been used.
&lt;/span&gt;            &lt;span style="color: rgb(0,0,255)"&gt;string&lt;/span&gt; x; 
        }

        &lt;span style="color: rgb(0,128,0)"&gt;// (4) Binds to local y. Error, usage before declaration.
&lt;/span&gt;        y = 10;
        &lt;span style="color: rgb(0,0,255)"&gt;string&lt;/span&gt; y;

        Func&amp;lt;&lt;span style="color: rgb(0,0,255)"&gt;int&lt;/span&gt;, &lt;span style="color: rgb(0,0,255)"&gt;int&lt;/span&gt;&amp;gt; f = x =&amp;gt; x + 1; &lt;span style="color: rgb(0,128,0)"&gt;// (5) Error, cannot redefine x.
&lt;/span&gt;        Func&amp;lt;&lt;span style="color: rgb(0,0,255)"&gt;int&lt;/span&gt;, &lt;span style="color: rgb(0,0,255)"&gt;int&lt;/span&gt;&amp;gt; g = z =&amp;gt; z + 1; &lt;span style="color: rgb(0,128,0)"&gt;// (6) OK. z has not been used.
&lt;/span&gt;    }
}
&lt;/pre&gt;&lt;a href="http://11011.net/software/vspaste"&gt;&lt;a href="http://11011.net/software/vspaste"&gt;&lt;/a&gt;
&lt;p&gt;The general rule of thumb is that the name will &lt;strong&gt;always&lt;/strong&gt; resolve to the local variable declared in the current scope if there is one, regardless of whether or not the name has been used to mean anything else in any scopes above it. In (2) above, one might think that x would bind to C.x, just like (1) did, but the spec is clear on this point - the name will always resolve to the local variable bound in the closest scope. 
&lt;h5&gt;2005 C# Compiler vs. 2008 C# Compiler&lt;/h5&gt;
&lt;p&gt;One thing that is worth mentioning is that in the 2008 C# Compiler, we fixed the error that is reported to be more in line with the specification. Consider the following code:&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;/span&gt;{
    &lt;span style="color: rgb(0,0,255)"&gt;void&lt;/span&gt; Foo()
    {
        &lt;span style="color: rgb(0,0,255)"&gt;int&lt;/span&gt; x;
        {
            &lt;span style="color: rgb(0,128,0)"&gt;// (1)
&lt;/span&gt;            &lt;span style="color: rgb(0,128,0)"&gt;// 2005 Compiler compiles this statement without errors.
&lt;/span&gt;            &lt;span style="color: rgb(0,128,0)"&gt;// 2008 Compiler yields CS0841: Cannot use variable 'x' 
&lt;/span&gt;            &lt;span style="color: rgb(0,128,0)"&gt;// before it is declared
&lt;/span&gt;            x = 5;

            &lt;span style="color: rgb(0,128,0)"&gt;// (2) 
&lt;/span&gt;            &lt;span style="color: rgb(0,128,0)"&gt;// 2005 Compiler yields CS0029: Cannot implicitly 
&lt;/span&gt;            &lt;span style="color: rgb(0,128,0)"&gt;// convert type 'string' to 'int'
&lt;/span&gt;            &lt;span style="color: rgb(0,128,0)"&gt;// 2008 Compiler yields CS0841: Cannot use variable 'x' 
&lt;/span&gt;            &lt;span style="color: rgb(0,128,0)"&gt;// before it is declared
&lt;/span&gt;            x = &lt;span style="color: rgb(163,21,21)"&gt;"s"&lt;/span&gt;;

            &lt;span style="color: rgb(0,128,0)"&gt;// (3)
&lt;/span&gt;            &lt;span style="color: rgb(0,128,0)"&gt;// 2005 and 2008 Compilers yield CS0136: A local variable 
&lt;/span&gt;            &lt;span style="color: rgb(0,128,0)"&gt;// named 'x' cannot 
&lt;/span&gt;            &lt;span style="color: rgb(0,128,0)"&gt;// be declared in this scope because it would give a 
&lt;/span&gt;            &lt;span style="color: rgb(0,128,0)"&gt;// different meaning to 'x', which is already used in a 
&lt;/span&gt;            &lt;span style="color: rgb(0,128,0)"&gt;// 'parent or current' scope to denote something else
&lt;/span&gt;            &lt;span style="color: rgb(0,0,255)"&gt;string&lt;/span&gt; x;
        }
    }
}&lt;/pre&gt;&lt;a href="http://11011.net/software/vspaste"&gt;&lt;a href="http://11011.net/software/vspaste"&gt;&lt;/a&gt;
&lt;p&gt;In the 2005 C# Compiler, we incorrectly bound both usages of x to the outer local variable, and so we would bind (1) perfectly fine, and we would report an error on (2) saying that string is not convertible to int. We would also report an error on (3), saying that you cannot redeclare x to be something else.&lt;/p&gt;
&lt;p&gt;In the 2008 C# Compiler, we fix this to correctly reflect the spec. Both (1) and (2) bind to (3), and since they are textually before their declaration, they both yield an error, saying that they are being used before they are declared. (3) also yields an error saying that you cannot redeclare x.&lt;/p&gt;
&lt;h5&gt;So what can we conclude?&lt;/h5&gt;
&lt;p&gt;Well I hope that helps clarify things a bit. I think the real thing that we should be concluding from this little exercise is that we should be choosing better names for our variables and fields! Descriptive names would help avoiding name clashing issues - if they don't, it's probably a sign that some refactoring is in order!&lt;/p&gt;&lt;a href="http://www.dotnetkicks.com/kick/?url=http%3a%2f%2fblogs.msdn.com%2fsamng%2farchive%2f2007%2f11%2f09%2flocal-variable-scoping-in-c.aspx"&gt;&lt;img alt="kick it on DotNetKicks.com" src="http://www.dotnetkicks.com/Services/Images/KickItImageGenerator.ashx?url=http%3a%2f%2fblogs.msdn.com%2fsamng%2farchive%2f2007%2f11%2f09%2flocal-variable-scoping-in-c.aspx" border="0"&gt;&lt;/a&gt;&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=6024701" 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/Variable+redeclaration/default.aspx">Variable redeclaration</category></item></channel></rss>