2013-05-22 64 views
63

爲什麼C#允許爲什麼C#允許語句之後的語句但不在它之前?

var s = "Nice"; 
switch (s) 
{ 
    case "HI": 
     break; 
    const string x = "Nice"; 
    case x: 
     Console.Write("Y"); 
     break; 
} 

但不是

var s = "Nice"; 
switch (s) 
{ 
    const string x = "Nice"; 
    case x: 
     Console.Write("Y"); 
     break; 
} 
+8

任何其他語言允許它? – Vivasaayi

+50

你爲什麼要這樣做? – Jodrell

+12

無論是否有人會寫這樣的代碼,這仍然是一個有趣的問題。幕後必須有一些奇怪的範圍界定。 –

回答

119

因爲你的縮進是誤導性的,第一個代碼居然是:

var s = "Nice"; 
switch (s) 
{ 
    case "HI": 
     break; 
     const string x = "Nice"; 
    case x: 
     Console.Write("Y"); 
     break; 
} 

x是在內部聲明的聲明(儘管在break之後),它在哪裏有效。但是,直接在switch聲明中它是無效的 - 唯一有效的聲明是casedefault

此外,const聲明是在編譯時評估,所以x是,即使之前有一個break語句定義。

但是請注意,Mono的C#編譯器不會編譯這段代碼,它抱怨說,「名字‘x’不當前範圍存在」,所以單似乎實現比.NET編譯更多的檢查。但是,我無法在C#標準中找到任何禁止使用const聲明的規則,所以我認爲.NET編譯器是正確的,而且Mono編譯器是錯誤的。

+2

但是如果它確實發生中斷,它怎麼顯示? – rtuner

+1

@rtuner我猜是因爲'const'聲明在編譯時被移到了方法的頂部。 – CodeCaster

+21

@rtuner'const'語句不在運行時執行,它們在編譯時被替換。嘗試並在其上放置一個斷點。 – Jodrell

7

因爲語言規範不直接使一個const在你開關(僅​​情況和默認被允許):

switch (expression) 
{ 
    case constant-expression: 
     statement 
     jump-statement 
    [default: 
     statement 
     jump-statement] 
} 

其中:

expression:的積分或字符串類型的表達式。
statement:如果將控制轉移到大小寫或缺省值,將執行的嵌入語句。
jump-statement:將控制權移出案例主體的跳轉聲明。
constant-expression:根據該表達式的值將控制轉移到特定的情況。

在第一種情況下,const是您的案例邏輯的一部分。常量只能在編譯時重寫,而不是在運行時重寫。

1

...因爲switch做到這一點

jump_to_the_label_matchig(s) 
{ 
    label1: 
     ... 
     done_quit_this; 
    label2: 
     ... 
     done_quit_this; 
    d'oh: 
     ... 
     done_quit_this; 
} 

,而不是這個

now_jump_to_the_label_matchig(s) 
{ 

    le'mme_wander_around_doing_things_that_could_have_been_done_before_me; 

    label1: 
     ... 
     done_quit_this; 
    label2: 
     ... 

我betcha當,如果這是允許的,你會發現人們願意做在那裏他們所有的編程: - )

相關問題