为什么针对可空值类型,“as”操作符给出null?

6
long? i = 10000;
int? s = i as int?;

为什么我的s变量显示为空值?我知道使用int? s = (int?)i;进行类型强制转换可以正常工作,但是为什么不能使用as运算符?

3
如果表达式的类型不同,as 运算符会返回 null,它不会尝试进行转换。当你使用 (int?)i 时,实际上是调用了一个显式操作符(而不是强制类型转换)来进行值的转换。 - Bradley Smith
3个回答

9

来自MSDN

该代码等同于以下表达式,只不过表达式变量仅被计算一次。

expression is type ? (type)expression : (type)null

由于i is int?为假,关键字as将返回(int?)null


如果我可以在可空值类型中使用 as,但它总是返回 null,那么为什么他们允许这样做呢? - Avinash Reddy
您可以将其用于可空值。例如:var s = i as object;并不返回null,因为int?是一个对象。但是,int?并不是long? - Loocid

3

这些类型不相等,因此你会得到null,这就是as的工作原理。

然而,你可以直接进行强制类型转换

long? i = 10000;
var s = (int?)i;

// or even better make sure its *checked* 

var s = checked((int?)i);

为什么这行得通?

C#语言规范11.6.1 Nullable转换

...

基于从S到T的基本转换进行可空转换评估的过程如下:

  • 如果可空转换是从S?T?
  • 如果源值为空(HasValue属性为false),则结果是类型为T?null值。
  • 否则,转换将作为从S?S的展开,然后是从ST的基本转换,最后是从TT?的包装。

...

as不会执行此操作,它检查运行时类型,如果它们不相等,则返回null T?


额外资源

checked (C# 参考)

checked 关键字用于显式启用整型算术运算和转换的溢出检查。

#更新评论

我知道我们不能进行转换,但为什么他们建议这样做呢?是否存在某种情况可以派上用场,例如一些随机图片链接 编译器错误 CS0077 "必须使用 as 运算符与引用类型或可空类型 ('int' 是非可空值类型)。"

原因是(在您的图像示例中)值类型不能为 null,因此无法使用它。您所忽略的是可能发生的更复杂的情况,您可以在自定义类型上定义 隐式 运算符等等。


如果我可以在可空值类型中使用 as,但它总是返回 null,那么为什么他们允许这样做呢? - Avinash Reddy
@avinash as 不起作用是因为它检查了类型。 - TheGeneral
我明白我们不能进行转换以及为什么不能这样做,但为什么他们建议这样做?是否存在某种情况下它会有用呢?ss - Avinash Reddy
@avinash 已更新 - TheGeneral

0

编译器无法将“long”隐式转换为“int”

根据MSDN的说法

as运算符类似于强制转换操作。但是,如果转换不可能,则as返回null而不是引发异常。

参考:as (C# Reference)

因此,使用您的代码进行转换是不可能的,as会返回Null。


long?long不同 - 你真的不能将as应用于值类型转换。所以不清楚这如何适用于问题。 (如果您希望我投反对票并发表评论,请告诉我-通常会因为帖子作者的报复而被视为不良做法)。 - Alexei Levenkov

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接