2011-03-22 34 views
1

也許這是早上剛剛太早,我是一個傻瓜,但我是一個有點困惑這個....使用'as'投射 - 爲什麼這不起作用?

SqlCommand cmd = new SqlCommand("prc_FooBar", conn)); 
object obj = cmd.ExecuteScalar(); 

// this is fine 
decimal? d = (decimal?)(obj as double?); 

// this doesn't compile 
decimal? d = (obj as double?) as decimal?; 

爲什麼不上一個版本編譯?

+0

你得到的錯誤是什麼?也是第一行是好的,它沒有給出運行時異常執行嗎? – 2011-03-22 09:48:44

+2

我的編譯器(4.0)不同意你在第二個「這很好」 – 2011-03-22 09:50:16

+0

是的抱歉,這是一個錯誤,我編輯 – fearofawhackplanet 2011-03-22 09:56:12

回答

6

as運算符與演員表不一樣。此博客解釋:

http://blogs.msdn.com/b/csharpfaq/archive/2004/03/12/what-s-the-difference-between-cast-syntax-and-using-the-code-as-code-operator.aspx

它僅在同一層級的「casts」類型之間,基本上遵循了「是」的想法。 A decimal?不是double?,但是編譯器可能會誘使您認爲它可能是因爲它在您丟失信息時明確爲您轉換它的時候生成(decimal?)myDouble;as運營商不會爲您這樣做,從而失敗。

更新:你問爲什麼有一個編譯器錯誤,而不是空結果。這是因爲as運營商永遠不可能得到double?decimal?。嘗試:

string s = ""; 
MyClass f = s as MyClass; 

開箱即用,這是行不通的,因爲編譯器知道這一點。得到編譯器錯誤比較好,因爲它無法在當前狀態下工作。

在正常使用情況下,如果類型實際上是您認爲的類型,則可以使用as運算符將強制類型轉換爲派生類型。然而,該類型可以是另一種派生類型(此編譯):

MyBase b = new MyDerived1(); 
MyDerived2 d = b as MyDerived2(); 

雖然技術上編譯器可以知道這(在某些情況下),如果它不將其與空,如果轉換失敗響應。

我敢肯定有人要一起去,並告訴我,我是多麼的錯誤是:-)

+0

但爲什麼它是一個錯誤,而不是隻解決'空'? (查看我對Jon Hanna的評論) – fearofawhackplanet 2011-03-22 10:17:14

+0

我已經更新了我的答案。 – 2011-03-22 10:33:27

3

docs

...的運營商只執行基準轉換和裝箱轉換。

double?轉換爲decimal?不適合這兩種類別,因爲沒有拳擊去,double?是不是一個亞型或decimal?超。

+0

因爲他使用小數?作爲類型,它實際上是一個引用類型:可爲空。 – Aidiakapi 2011-03-22 09:56:37

+2

@Aidiakapi:'可爲空'是* not *引用類型,儘管編譯器允許可以在某些方式中模仿ref類型的行爲。 http://msdn.microsoft.com/en-us/library/b3h38hb0.aspx – LukeH 2011-03-22 10:05:22

+0

@LukeH,感謝糾正我,有人告訴我,這是我認爲是誰的原因。 – Aidiakapi 2011-03-22 10:08:27

1

var x = v as X等同於:

var v = v is X ? (X)v : null;但只有單一類型的檢查操作發生((X)v自己檢查v是否或可以轉換爲X,否則拋出異常)。

double? tmp = obj is double? ? (double?)obj : null; 
decimal? d = tmp is decimal? ? (decimal?)tmp : null; 

它在編譯時真實已知tmpdouble?(具有一個值,或者沒有值使它等於null):以

你的後一種情況下是相等的。因此tmp is decimal?的測試總是錯誤的,並且在編譯時操作失敗。

+0

這是一個非常明確的解釋,謝謝。這種行爲似乎很奇怪,但......你似乎在說「雙重」的唯一原因?作爲十進制?'是編譯時錯誤是因爲編譯器確定結果將始終爲空,但是我可以愉快地將'null作爲十進制?'寫入而不出錯。 – fearofawhackplanet 2011-03-22 10:17:40

+0

'as'旨在用於投射,因此有人試圖做不可能的投射可能有一個錯誤。編譯器已經救了你,因爲如果它每次只給null賦值d就很難找到並修復它。 – 2011-03-22 10:21:06