[英]Casting with 'as' - why doesn't this work?
也許還為時過早,我是個白痴,但對此我有些困惑。
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?;
為什么最后一個版本不編譯?
as
運算符與強制類型轉換不同。 該博客說明:
它基本上只是在遵循“是”概念的情況下,才在相同層次結構中的類型之間“轉換”。 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();
盡管從技術上來說 ,編譯器可以知道這一點(在某些情況下),但如果不知道,則如果強制轉換失敗,它將以null進行響應。
我確定有人會來告訴我我錯了:-)
從文檔 :
... as運算符僅執行參考轉換和裝箱轉換。
從double?
轉換double?
到decimal?
這兩個類別都不適合,因為沒有拳擊動作,並且double?
是decimal?
的子類型還是超類型decimal?
。
var x = v as X
等效於:
var v = v is X ? (X)v : null;
但僅發生一次類型檢查操作( (X)v
自己檢查v是否為X或可以強制轉換為X,否則拋出異常)。
您的后一種情況等效於:
double? tmp = obj is double? ? (double?)obj : null;
decimal? d = tmp is decimal? ? (decimal?)tmp : null;
在編譯時知道tmp
是double?
(具有一個值或沒有值使其等於null
)。 tmp is decimal?
的測試tmp is decimal?
因此始終為false,並且該操作在編譯時失敗。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.