C# 用'铸造;作为';-为什么';这不管用吗?

C# 用'铸造;作为';-为什么';这不管用吗?,c#,ado.net,casting,type-conversion,C#,Ado.net,Casting,Type Conversion,也许现在还太早,我是个白痴,但我对此有点困惑 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?; 为什么最后一个版本不

也许现在还太早,我是个白痴,但我对此有点困惑

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运算符仅执行引用转换和装箱转换

double?
转换到
decimal?
不适合这两个类别,因为没有装箱操作,而且
double?
不是
decimal?
的子类型或超类型:

。。。as运算符仅执行引用转换和装箱转换


double?
转换到
decimal?
不适合这两种类型,因为没有装箱,而且
double?
不是
decimal?

的子类型或超类型
as
操作符与cast不同。本博客解释:

它只在同一层次结构中的类型之间进行“强制转换”,基本上遵循“is-a”的思想。
decimal?
不是
double?
,但是当您使用
(decimal?)myDouble时,编译器可能会欺骗您,使您认为它可以因为它显式地为您强制转换它,同时丢失信息。
as
操作员不为您执行此操作,因此失败

更新:您会问为什么会出现编译器错误而不是空结果。这是因为
as
运算符永远无法将
double?
转换为
decimal?
。尝试:

string s = "";
MyClass f = s as MyClass;
开箱即用,这不起作用,因为编译器知道这一点。最好得到一个编译器错误,因为它永远不能在当前状态下工作

在正常使用情况下,如果基本类型实际上是您认为的类型,则可以使用
as
操作符将其转换为派生类型。但是,该类型可以是另一个派生类型(这将编译):

虽然编译器在技术上可能知道这一点(在某些情况下),但如果它不知道,则在强制转换失败时将以null响应


我肯定会有人来告诉我我错了:-)

作为
操作符的
与演员不一样。本博客解释:

它只在同一层次结构中的类型之间进行“强制转换”,基本上遵循“is-a”的思想。
decimal?
不是
double?
,但是当您使用
(decimal?)myDouble时,编译器可能会欺骗您,使您认为它可以因为它显式地为您强制转换它,同时丢失信息。
as
操作员不为您执行此操作,因此失败

更新:您会问为什么会出现编译器错误而不是空结果。这是因为
as
运算符永远无法将
double?
转换为
decimal?
。尝试:

string s = "";
MyClass f = s as MyClass;
开箱即用,这不起作用,因为编译器知道这一点。最好得到一个编译器错误,因为它永远不能在当前状态下工作

在正常使用情况下,如果基本类型实际上是您认为的类型,则可以使用
as
操作符将其转换为派生类型。但是,该类型可以是另一个派生类型(这将编译):

虽然编译器在技术上可能知道这一点(在某些情况下),但如果它不知道,则在强制转换失败时将以null响应


我肯定会有人来告诉我我错了多少:-)

var x=v,因为x
相当于:

double? tmp = obj is double? ? (double?)obj : null;
decimal? d = tmp is decimal? ? (decimal?)tmp : null;
var v=v是X?(十) v:空
但仅发生一个类型检查操作(
(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的测试是十进制的?
因此总是错误的,并且操作在编译时失败。

var x=v as x
相当于:

double? tmp = obj is double? ? (double?)obj : null;
decimal? d = tmp is decimal? ? (decimal?)tmp : null;
var v=v是X?(十) v:空
但仅发生一个类型检查操作(
(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的测试是十进制的?
因此总是错误的,并且操作在编译时失败。

您得到的错误是什么?还有第一行很好,它执行时是否没有给出运行时异常?我的编译器(4.0)在第二行“这很好”上不同意您的意见是的,对不起,这是一个错误,我已经编辑了您得到的错误是什么?还有第一行很好,它执行时是否没有给出运行时异常?我的编译器(4.0)在第二行“这很好”上不同意您的意见是的,对不起,这是一个错误,我编辑过,因为他使用十进制?作为类型,它实际上是一个引用类型:Nullable。@Aidiakapi:
Nullable
不是引用类型,尽管编译器允许nullables以某种方式模拟ref类型的行为@LukeH,谢谢你纠正我,有人告诉我是谁,我猜是谁。我最初是在评论我认为它属于的情景,但你后来编辑了你的答案,所以我的评论毫无意义!:-)因为他用十进制?作为类型,它实际上是一个引用类型:Nullable。@Aidiakapi:
Nullable
不是引用类型,尽管编译器允许nullables以某种方式模拟ref类型的行为@LukeH,谢谢你纠正我,有人告诉我是谁,我猜是谁。我最初是在评论我认为它属于的情景,但你后来编辑了你的答案,所以我的评论毫无意义!:-)但是w