为什么C#ä¸å…许我在ä¸åŒçš„范围内使用相åŒçš„å˜é‡å?

时间:2011-01-10 18:11:14

标签: c# .net compiler-construction

例如:

if ( this.IsValid )
{
    Matrix matrix = new Matrix();
}

Matrix matrix = new Matrix();

编译器警告我说:

“å为'matrix'的局部å˜é‡ä¸èƒ½åœ¨æ­¤èŒƒå›´å†…声明,因为它会给'matrix'赋予ä¸åŒçš„å«ä¹‰ï¼Œ'matrix'已在'å­'范围内用于表示æŸäº›å†…容其他

这些å˜é‡ä¸æ˜¯åœ¨ä¸åŒçš„范围内,所以我无法从if语å¥ä¹‹å¤–访问第一个{{1}}å—?

5 个答案:

答案 0 :(得分:16)

更新:2011年以下的答案对于早期版本的C#是正确的;在更新的版本中,规则æ述的答案已从C#中删除。设计团队确定该规则引起开å‘人员之间更多的混淆,导致åƒè¿™æ ·çš„问题,而ä¸æ˜¯æœ‰ç¼ºé™·çš„程åºå¯ä»¥ä¿è¯ï¼Œå³ä½¿åœ¨æˆ‘大大改进了错误消æ¯ä»¥æ›´æ¸…楚地诊断问题之åŽã€‚


到目å‰ä¸ºæ­¢ç»™å‡ºçš„答案éžå¸¸ä»¤äººå›°æƒ‘。正确分æžé—®é¢˜çš„方法是读å–错误消æ¯ã€‚错误消æ¯å‘Šè¯‰æ‚¨å®žé™…上是错误的:

  

“å为'matrix'的局部å˜é‡ä¸èƒ½åœ¨æ­¤èŒƒå›´å†…声明,因为它会给'矩阵'赋予ä¸åŒçš„å«ä¹‰ï¼Œ'矩阵'已在'å­'范围内用于表示其他内容。

仔细阅读 。它正在告诉你C#的哪个规则被è¿å,å³ä½ ä¸å…许使用相åŒçš„å称æ¥å¼•ç”¨åŒä¸€èŒƒå›´å†…的两个ä¸åŒçš„东西。 (实际上,错误信æ¯æœ‰ç‚¹é”™è¯¯;它应该说“局部å˜é‡å£°æ˜Žç©ºé—´â€ï¼Œå®ƒè¡¨ç¤ºâ€œèŒƒå›´â€ï¼Œä½†è¿™å¾ˆç½—嗦。)

此规则记录在C#4.0规范的第7.6.2.1节中:简å•å称,å—中的ä¸å˜å«ä¹‰ã€‚

(在é‡å å£°æ˜Žç©ºé—´ä¸­æœ‰ä¸¤ä¸ªç›¸åŒå称的局部å˜é‡ï¼Œä¹Ÿéžæ³•ã€‚编译器也å¯èƒ½æŠ¥å‘Šè¯¥é”™è¯¯ï¼Œä½†åœ¨è¿™ç§æƒ…况下报告更一般的错误。 )

  

这些å˜é‡ä¸æ˜¯åœ¨ä¸åŒçš„范围内,所以我无法从if语å¥å¤–部访问第一个矩阵å—?

是。该声明 true 但无关。这里的错误是使用相åŒçš„简å•å称æ¥å¼•ç”¨åŒä¸€å±€éƒ¨å˜é‡å£°æ˜Žç©ºé—´ä¸­çš„两个ä¸åŒçš„东西。

考虑这ç§æƒ…况:

class C 
{
    int x;
    void M()
    {
        x = 10; // means "this.x"
        for(whatever)
        {
            int x = whatever;
        }
    }
 }

åŒæ ·çš„交易。这里的错误是在外部声明空间中使用简å•å称“xâ€æ¥å¼•ç”¨this.x,并且在内部声明空间中使用它æ¥è¡¨ç¤ºâ€œå±€éƒ¨å˜é‡â€ã€‚使用相åŒçš„简å•å称在åŒä¸€ä¸ªå£°æ˜Žç©ºé—´ä¸­å¼•ç”¨ä¸¤ä¸ªä¸åŒçš„东西 - è®°ä½ï¼Œå†…部声明空间是外部声明空间的部分 - 是令人困惑的和å±é™©çš„,因此是éžæ³•çš„。

由于显而易è§çš„原因令人困惑;一个人有一个åˆç†çš„期望,一个å称在它首次使用的声明空间的任何地方都æ„味ç€ç›¸åŒçš„东西。这很å±é™©ï¼Œå› ä¸ºå°ä»£ç ç¼–辑很容易改å˜å«ä¹‰ï¼š

class C 
{
    int x;
    void M()
    {
        int x;
        x = 10; // no longer means "this.x"
        for(whatever)
        {
            x = whatever;
        }
    }
 }

如果首次使用简å•å称的声明空间ä¸é‡å ï¼Œé‚£ä¹ˆç®€å•å称引用ä¸åŒçš„东西是åˆæ³•çš„:

class C 
{
    int x;
    void M()
    {
        {
            x = 10; // means "this.x"
        }
        for(whatever)
        {
            int x = whatever; // Legal; now the 
        }
    }
 }

有关油炸食å“的更多信æ¯å’Œæœ‰è¶£æ•…事,请å‚阅

http://blogs.msdn.com/b/ericlippert/archive/tags/simple+names/

答案 1 :(得分:7)

我认为这样åšæ˜¯ä¸ºäº†é¿å…模糊的错误或难以阅读的代ç ã€‚

在方法范围和å­èŒƒå›´ä¹‹é—´ä½¿ç”¨ç›¸åŒçš„å˜é‡å称会导致代ç éžå¸¸éš¾ä»¥é˜…读,因为å˜é‡ç±»åž‹ï¼Œæ›´ç³Ÿç³•çš„是,æ„义å¯ä»¥æ”¹å˜ï¼Œè€Œå”¯ä¸€çš„æ示读者将在å˜é‡ä¹‹å‰è¾“入类型声明关键字。

但是,我也å¯ä»¥å‘Šè¯‰ä½ ï¼ŒC#编译器为方法生æˆçš„IL会将所有å˜é‡å£°æ˜Žéƒ½æ”¾åœ¨é¡¶éƒ¨ï¼Œæ‰€ä»¥è¿™ä¸ªå†³ç­–驱动程åºå¯èƒ½æ˜¯ä¸ºäº†ç®€åŒ–编译器的å˜é‡è§£æžæ ‘。

事实上,您å¯ä»¥åœ¨MSDN上找到它:

  

å称的范围是。的区域   它所在的程åºæ–‡æœ¬   å¯ä»¥å¼•ç”¨è¯¥å®žä½“   没有通过å称声明   å称的资格。范围å¯ä»¥   嵌套,内部范围å¯ä»¥   é‡æ–°å£°æ˜Žä¸€ä¸ªåå­—çš„å«ä¹‰   外部范围。 (这ä¸ï¼Œ   但是,å–消é™åˆ¶   由Section 3.3强加的   嵌套å—是ä¸å¯èƒ½çš„   声明一个具有相åŒçš„局部å˜é‡   name作为一个局部å˜é‡   å°é—­å—。)æ¥è‡ªçš„å称   然åŽè¯´å¤–部范围是éšè—çš„   在所涵盖的计划文本范围内   由内部范围,并访问   外部å称åªèƒ½é€šè¿‡   é™å®šå称。

强调增加。

并且,从第3.3节开始:

  

æ¯ä¸ªå—或开关å—创建一个   当地的ä¸åŒç”³æŠ¥ç©ºé—´   å˜é‡å’Œå¸¸é‡ã€‚å字是   介ç»åˆ°è¿™ä¸ªå®£è¨€ç©ºé—´   通过局部å˜é‡å£°æ˜Ž   和局部常é‡å£°æ˜Žã€‚如果一个   block是实例的主体   构造函数,方法或è¿ç®—符   声明,或获å–或设置访问者   对于索引器声明,   在这样的声明中声明的å‚æ•°   声明是å—çš„æˆå‘˜   局部å˜é‡å£°æ˜Žç©ºé—´ã€‚该   一个局部å˜é‡å£°æ˜Žç©ºé—´   å—包括任何嵌套å—。   因此,在嵌套å—中它ä¸æ˜¯   å¯ä»¥å£°æ˜Žä¸€ä¸ªå±€éƒ¨å˜é‡   与本地å˜é‡åŒå   在一个å°é—­çš„区å—。

强调增加。

所以,问题是虽然范围ä¸åŒï¼Œä½†å˜é‡ç©ºé—´æ˜¯ç›¸åŒçš„。

答案 2 :(得分:5)

你总是å¯ä»¥è¿™æ ·åš......

void YourMethod() 
{
    if ( this.IsValid ) 
    {    
        Matrix matrix = new Matrix();
    }

    {
        Matrix matrix = new Matrix(); 
    }
}

...æ¯ç»„大括å·{}å…许您嵌套å¦ä¸€ä¸ªèŒƒå›´çš„范围。您é‡åˆ°çš„问题是嵌套范围包括其父级的范围。如果声明siblng范围,它将能够在åŒä¸€çˆ¶çº§ä¸­é‡ç”¨å˜é‡ã€‚但正如其他人所指出的那样,这å¯èƒ½ä¼šåœ¨ä»¥åŽå˜å¾—混乱。

答案 3 :(得分:2)

想象一下,人类正在å°è¯•é˜…读此代ç ã€‚

从å¦ä¸€ä½è¯•å›¾é˜…读您的代ç çš„å¼€å‘人员的角度æ¥çœ‹ï¼Œä½ èƒ½çœ‹åˆ°ä¸¤ä¸ªä¸åŒçš„åŒåå˜é‡æœ‰å¤šä¹ˆä»¤äººå›°æƒ‘å—?å³ä½¿ä»–们代表åŒæ ·çš„事情,也很难处ç†åŒå的两件事。

答案 4 :(得分:1)

Matrix matrix = new Matrix();

if ( this.IsValid ) 
{
    Matrix matrix = new Matrix(); 
} 

想象一下,它是这样编写的,更明显我会想到为什么ä¸å…许这样åšï¼Œå› ä¸ºç¬¬äºŒä¸ªå®žä¾‹æ˜¾ç„¶åº”该被视为冲çªã€‚无法访问å­èŒƒå›´å†…的外部å˜é‡ä¼šå¾ˆç³Ÿç³•ã€‚

æ¥è‡ªMSDN“A:这是正确的行为,并在语言规范的3.7节中介ç»ã€‚它说,â€åœ¨local-variable-declaration(8.5.1)中声明的局部å˜é‡çš„范围是å—在声明å‘生的地方“。†......“这ç§è¡Œä¸ºæ„图ä¸å¤ªå¯èƒ½é‡å¤ä½¿ç”¨å˜é‡å称(例如剪切和粘贴)。†(http://blogs.msdn.com/b/csharpfaq/archive/2004/05/18/why-can-ti-use-the-same-variable-as-an-inner-loop-does.aspx)< / p>