2012-03-14 58 views
1

我只是在幕后讨论什么。我有这个代码,当然它不会编译,因为我在if语句中创建hello变量,然后尝试声明它是简单的。为什么不让.NET允许我这样做?在这些场景后面发生什么可能会导致hello变量干扰陈述中的变量。.NET如何处理范围内的变量

这是非常直截了当的为什么这可能会干扰如果该变量是在if语句之前声明的。

public void Test() { 
     if (true) 
     { 
      var hello = ""; 
     } 
     var hello = ""; 

     Console.Write(hello); 
    } 
+4

顺便说一句,这是_C#_,而不是.Net。 .Net没有范围的概念。 – SLaks 2012-03-14 15:43:18

+0

http://msdn.microsoft.com/en-us/library/ms973875.aspx – 2014-01-13 15:18:57

回答

4

只是为了澄清,这里违反了两条规则。

第一个是嵌套的局部变量声明空间可能不包含两个相同名称的声明。

二是嵌套本地范围可能不包含相同简单的名称声明的两种用法是指两个不同的东西。

这两个规则都被违反了。请注意,第一条规则基本上是第二条规则的特例。第二条规则更一般;例如,这也是一个违规:

class C 
{ 
    int x; 
    void M() 
    { 
     if (whatever) 
     { 
      string x = ""; 
     } 
     x = 10; 
    } 
} 

这里简单名称x用于表示在一个本地作用域this.x和在嵌套范围局部变量x。这很混乱;在整个块中需要一个简单的名称来表示相同的事物。因此我们认为它是非法的。这将是合法的:

class C 
{ 
    int x; 
    void M() 
    { 
     if (whatever) 
     { 
      string x = ""; 
     } 
    } 
} 

即使局部变量被嵌套在该领域的范围内的范围内声明的,这是允许的,因为该领域的范围是不是一个局部变量声明空间。

这也是合法的:

class C 
{ 
    int x; 
    void M() 
    { 
     if (whatever) 
     { 
      string x = ""; 
     } 
     else 
     { 
      x = 2; 
     } 
    } 
} 

因为现在的x两个相互矛盾的用法都始终贯穿其直接包含范围的条款内容使用。那些范围现在不重叠,所以这是允许的。 (然而,这仍然是一个糟糕的主意。)

这些规则是为了您的安全,但它们可能会令人困惑。见

http://blogs.msdn.com/b/ericlippert/archive/tags/declaration+spaces/

http://blogs.msdn.com/b/ericlippert/archive/tags/scope/

对这些语言特性的文章。

+0

哇,谢谢你;-) – 2012-03-14 18:37:19

+0

“但它仍然是一个坏主意”< - 轻描淡写警报! – phoog 2012-03-14 21:37:25

5

名称的声明空间甚至延伸的声明之前,以填补其整个块。
参见Eric Lippert's blog post

+0

伟大的,就像我想要的东西;-) – 2012-03-14 15:46:49

+0

只是为了澄清:虽然它是*真*,名称是在包含其声明的整个区块的范围内,实际上在这里违反了两条规则。首先是*嵌套局部变量声明空间*不能包含两个同名的声明。第二个是*嵌套范围*可能不包含两个*简单名称或声明*,它们引用不同的东西。 – 2012-03-14 16:50:05

+0

@EricLippert:我在这里等你的智慧,我没有失望:) – SLaks 2012-03-14 17:09:30

2

http://msdn.microsoft.com/en-us/library/aa691132(v=vs.71).aspx

一个名字的范围是程序文本的区域内,它可能是指不名的资格由名称声明的实体。范围可以嵌套,并且内部范围可以从外部范围重新声明名称的含义。 (然而,这并没有消除3.3节的限制,即在一个嵌套块中不可能声明一个局部变量与局部变量的局部变量具有相同的名称)来自外部作用域的名称然后被认为隐藏在内部范围覆盖的程序文本区域中,并且只有通过限定名称才能访问外部名称。