2016-11-16 47 views
0

我學習C#和跨越,使我對它的語法有點不舒服了幾件事情來了。不一致的C#語言的語法

案例1

byte num1 = 10; // works 
int ten = 10; 
byte num2 = ten; // Compile error: Cannot implicitly convert 'int' to byte. An explicit conversion exists. 

在第一條語句編譯器隱蒙上文字10(類型爲int)以字節,相反它不會做的第三條語句相同。

案例2

int[] numbers1 = { 10, 20, 30 };  // works 
int[] numbers2; 
numbers2 = { 10, 20, 30 };   // Compiler error: Invalid expression term: { 

以上縮短陣列初始化不會每個語句工作。

,可能有更多的這種不一致......

看來錯誤的版本是正確的,因爲這些都是按照規定的語法,並沒有錯誤版本(類似的情況)是語言創建結構只是使語言易於編碼。

但是仍然不應該在我們使用它的每個地方保持一致?

+8

你不是指語法,而是語法。 –

+4

數組初始化只能在初始化數組時使用,而不能在數組初始化後使用。 「初始化」是指在此情況下「構建時」。你不能用這個語法分開初始化和聲明。 –

+0

@MatthewWatson - 'numbers2'只被聲明,即它尚未初始化。 –

回答

10

案例1是一種特殊的情況下,由C#語言規範明確地覆蓋。

§6.1.9隱式常量表達式轉換

隱式常量表達式轉換允許以下 轉化:

•類型的常量表達式(§7.19) int可以是 轉換爲sbyte,byte,short,ushort,uint或ulong類型,只要提供 常量表達式的值在 destina範圍內類型。

•long類型的常量表達式可以是 轉換爲ulong類型,前提是常量表達式 的值不是負數。

因爲變量ten未聲明爲const那麼上述規則不適用,並沒有隱式轉換是允許的,你會得到一個編譯錯誤。

請注意,如果你改變tenconst int ten = 10;那麼工作,因爲,當然,它現在是一個常數。

案例2通過運營商new的功能啓用。

§1。8個陣列

新操作者允許的數組元素的初始值,使用數組初始化,這是定界符{和}之間的表達式列表中指定。

以下示例使用三個元素分配並初始化一個int []。

int [] a = new int [] {1,2,3};

請注意,數組的長度是從{和}之間的表達式數推斷的。局部變量和字段聲明可以進一步縮短,使得數組類型不必重述。

int [] a = {1,2,3};

觀察它如何讓你忽略new關鍵字,即使它是實際使用的幕後操作者new

因此,由於此語法糖由new運算符提供,因此只能在隱式使用new時使用。

在您的例子,當你單獨的聲明和初始化你仍然可以部分地使用這個語法,但你必須明確地使用new關鍵字:

int[] numbers2; 
numbers2 = new [] { 10, 20, 30 }; 

現在你可能會說,編譯器可能允許沒有new的語法,因爲它知道numbers2的類型,並且可以推斷出存在{}意味着它必須是數組初始化。然而,這需要一個新的規則,我想像語言設計者並不認爲它會被用來證明添加它是正確的。

+0

謝謝你的回答。 $ 6.1.9很好地解釋了案例1。 對於案例2,我覺得語法糖也應該支持第二種說法。 –

+1

@SurajGharat我懷疑語言設計師並不是真的想要支持將分離聲明和分配放在必要之外 - 爲此添加明確的支持是鼓勵應該被忽視的編程實踐! –

4

在case1中,您正在使用文字進行初始化。這

byte b = 10; 

是好的,因爲文字「10」是一個有效的字節。將變量賦值給另一個變量而不是文字是不一樣的。 在下面的例子,想象一下,如果我們這樣做:

int ten = 10; 
ten = 100000; // evil 
byte b = ten; 

第一種情況,只是因爲C#是試圖盡力解釋「10」文字作爲一個字節的相當不錯。它可以這樣做,因爲它在編譯時有的值,它是0..255。當從ten分配值時,它無法知道值被限制爲0..255,因此它必須失敗或靜默截斷。在C#的情況下,行爲是失敗的。

在情況2中,您正在使用「數組初始值設定語法」。奇怪的是,這僅適用於數組初始化程序而不是作爲表達式使用。我實際上不確定這是爲什麼,也許是因爲語法模糊。與您可能認爲的相反,表達式{1, 2, 3}而不是new int[] {1, 2, 3}的簡寫,它只在初始化程序中使用時才起作用。

如果你想你(也許)擬在個案2中,你將不得不使用全(非初始化)表達什麼:

int[] numbers1 = new int[] { 10, 20, 30 };  
int[] numbers2; 
numbers2 = new int[] { 20, 30, 40 }; 

編輯:正如在評論中指出有非初始化程序數組創建的簡寫:您可以像這樣刪除數組類型,只有在可以從值中推斷出類型的情況下才能執行new[] {10, 20, 30}

+0

在這種特殊情況下,數組創建的'int'部分可以被刪除:'new [] {10,20,30}'將創建一個'int []',因爲每個項都是'int' 。 – Kyle

+0

添加到答案中,謝謝。 –