也许现在早上太早了,我是个白痴,但我对此感到有些困惑....
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 :(得分:6)
as
运算符与强制转换不同。这篇博客解释说:
它只在同一层次结构中的类型之间“强制转换”,基本上遵循“is-a”的想法。 decimal?
不是double?
,但是编译器会诱使您认为它可以在(decimal?)myDouble;
时出现,因为它会在丢失信息时为您明确地投射它。 as
运算符不会为您执行此操作,因此会失败。
更新:您问为什么存在编译器错误而不是null结果。这是因为as
运算符永远无法将double?
传递给decimal?
。尝试:
string s = "";
MyClass f = s as MyClass;
开箱即用,这不起作用,因为编译器知道这一点。最好得到一个编译器错误,因为它永远不能在它的当前状态下工作。
在正常使用情况下,如果类型实际上是您认为的类型,则可以使用as
运算符将转换基类型转发为派生类型。但是,类型可以是另一种派生类型(编译):
MyBase b = new MyDerived1();
MyDerived2 d = b as MyDerived2();
虽然编译器在技术上可以知道这种情况(在某些情况下),如果不是,如果转换失败,它会以null响应。
我确定有人即将到来告诉我我有多错: - )
答案 1 :(得分:3)
答案 2 :(得分: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;
在编译时已知tmp
是double?
(带有值,或没有值使其等同于null
)。因此,tmp is decimal?
的测试始终为false,并且在编译时操作失败。