2010-03-22 145 views
56

在另一個論壇上出現了一個問題,我知道如何解決它,但它揭示了編譯器特有的一個特性。該人收到錯誤「嵌入式語句不能是聲明或標記語句」,因爲他們在if語句後沒有括號的情況下聲明瞭變量。這不是他們的意圖,但是他們已經將if語句之後的代碼行註釋掉了,這使得變量聲明成爲事實上的代碼行來執行。無論如何,這是背景,這使我想到了這一點。if語句後面的變量聲明

下面的代碼是非法的

if (true) 
    int i = 7; 

但是,如果包裹在括號中,它的所有法律。

if (true) 
{ 
    int i = 7; 
} 

這兩段代碼都沒有用。然而第二個是確定的。這個行爲的具體解釋是什麼?

回答

76

C# language specification三種類型的語句(參見第8章區分調出更多細節)。一般來說,你可以有以下語句:

  • 標記語句 - 我的猜測,這是老式goto聲明
  • 聲明,聲明 - 這將是一個變量聲明
  • 嵌入語句 - 其中幾乎包含所有其餘的語句

if聲明機構必須是嵌入式聲明,這解釋了爲什麼代碼的第一個版本不起作用。以下是規範中的if的語法(第8.7節)。1):

if (boolean-expression) embedded-statement
if (boolean-expression) embedded-statement else embedded-statement

變量聲明是聲明陳述,因此它不能在體內出現。如果將括號內的聲明括起來,您將得到一個聲明塊,這是一個嵌入語句(因此它可以出現在該位置)。

27

如果不包含括號,它會執行下一行,就像它被括號括起來一樣。由於在該行中聲明一個變量沒有多大意義(您將無法使用該變量),因此C#編譯器不會允許您在不知情的情況下意外執行該操作(這可能會引入細微的錯誤)。

這裏的埃裏克利珀的部分必須說關於this SO answer C#編譯器有關名稱解析:

...C# is not a "guess what the user meant" language...the compiler by design complains loudly if the best match is something that doesn't work

+1

我同意加括號,它沒有任何意義可言申報以這種方式變化。然而,第二個例子中完全無用的變量聲明沒有問題。沒有價值。這僅僅是一個括號問題,沒有別的? (順便說一句,我可以和他一起生活)。 – 2010-03-22 23:58:26

+3

是的。當你包含括號時,你的意圖對編譯器來說是絕對清楚的,所以它會允許的。 C#編譯器不會在沒有括號的情況下允許它,因爲不清楚您的實際意圖是聲明無用變量。 – 2010-03-23 00:00:37

+0

但是第二個可能非常有價值 - 例如,如果從具有副作用的方法中檢索值。 – 2010-03-23 00:08:49

9

所有的編譯器將允許您編譯代碼,無用或極低的使用。開發人員可以使用該語言創建沒有用處的結構的方式太多了。讓編譯器抓住所有這些都是非常費力,通常不值得。

第二種情況是直接在C#語言規範在區間的開始8.0

The example results in a compile-time error because an if statement requires an embedded-statement rather than a statement for its if branch. If this code were permitted, then the variable i would be declared, but it could never be used. Note, however, that by placing i’s declaration in a block, the example is valid.

示例代碼

void F(bool b) { 
    if (b) 
     int i = 44; 
} 
+0

感謝您的意見,非常有益。 – 2010-03-23 00:14:25

0

在if的其他部分添加閉合和開啓大括號,就像我在下面做的那樣幫助我,而不是在添加它們之前做的事情;

之前:這引起了錯誤:

protected void btnAdd_Click(object sender, EventArgs e) 
    { 
     if (btnAdd.Text == "ADD") 
     { 

      CATEGORY cat = new CATEGORY 
      { 

       NAME = tbxCategory.Text.Trim(), 
       TOTALSALEVALUE = tbxSaleValue.Text.Trim(), 
       PROFIT = tbxProfit.Text.Trim() 

      }; 
      dm.AddCategory(cat, tbxCategory.Text.Trim()); 
     } 
     else 
     // missing brackets - this was causing the error 
      var c = getCategory(); 
      c.NAME = tbxCategory.Text.Trim(); 
      c.TOTALSALEVALUE = tbxSaleValue.Text.Trim(); 
      c.PROFIT = tbxProfit.Text.Trim(); 
      dm.UpdateCategory(c); 

     btnSearchCat_Click(btnSearchCat, e); 
    } 

後:在else分支

protected void btnAdd_Click(object sender, EventArgs e) 
    { 
     if (btnAdd.Text == "ADD") 
     { 

      CATEGORY cat = new CATEGORY 
      { 

       NAME = tbxCategory.Text.Trim(), 
       TOTALSALEVALUE = tbxSaleValue.Text.Trim(), 
       PROFIT = tbxProfit.Text.Trim() 

      }; 
      dm.AddCategory(cat, tbxCategory.Text.Trim()); 
     } 
     else 
     { 
      var c = getCategory(); 
      c.NAME = tbxCategory.Text.Trim(); 
      c.TOTALSALEVALUE = tbxSaleValue.Text.Trim(); 
      c.PROFIT = tbxProfit.Text.Trim(); 
      dm.UpdateCategory(c); 
     } 
     btnSearchCat_Click(btnSearchCat, e); 
    }