为什么 'Convert.ToInt32' 和 'as int?' 的工作方式不同?

3
Convert.ToInt32(myCommand.ExecuteScalar()); // Returns 100, because myCommand is a SQL command that gets a non-null BigInt cell
myCommand.ExecuteScalar() as int? ?? 0; //Returns 0 even when myCommand is SQL command that gets a non-null BigInt cell

在这种情况下,我必须使用第二种方法,因为myCommand.ExecuteScalar()可能返回 DBNull 。但是为什么第二种方法返回的结果与 Convert.ToInt32 不同呢?

编辑:谢谢大家。将类型更改为Int64,现在它可以正常工作。


as 永远不会执行表示形式的转换:http://blogs.msdn.com/b/ericlippert/archive/2009/10/08/what-s-the-difference-between-as-and-cast-operators.aspx - Mike Zboray
2个回答

9

转换和强制类型转换(使用cast运算符,is运算符和as运算符)是两个不同的概念:

  • 转换是将一种类型转换为另一种类型。例如从stringInt64转换为Int32
  • 强制类型转换只能从基类转换为派生类。在这种情况下,从objectInt32。要成功转换,object必须包含一个Int32。在您的情况下,它没有,转换将返回null

代码示例:

Int64 l = 100;
object o = l;
Int32 i1 = o as Int32? ?? 0; // Cast fails, so "as" will return 0. "??" will make it 0.
Int32 i2 = Convert.ToInt32(o); // The Int32 inside the object will be converted into an Int32 and will return 100.

@newStackExchangeInstance 你说得没错,但只有在你非常严谨的情况下才是这样的:o as int 是无效的,错误是:“必须使用引用类型或可空类型的 as 运算符”。因此,as 不能返回 default(int),但它可以返回 default(int?),从技术上讲它不是 null,但几乎与 null 处理方式相同。 - Tim S.
实际上,这两个强制类型转换运算符(c风格的()as)也是不同的。as永远不会执行转换。 - Mike Zboray
@newStackExchangeInstance - as不能捕获强制转换异常 - 它使用isinst IL指令,如果参数不是指定类型的实例,则返回null。 - Lee
@newStackExchangeInstance:as不会捕获任何异常。它基本上是x is SomeType ? (SomeType)x : null的简写形式。 - siride
但你必须承认(double)5不是一个强制转换,而是一个转换。C#不称其为“重写强制转换运算符”,而是称之为“转换运算符”(参见:http://msdn.microsoft.com/en-us/library/09479473(v=vs.80).aspx)。所以`is`和`as`始终与强制转换有关。`(T)value`则涉及到强制转换或转换。 - Martin Mulder
显示剩余5条评论

2

Convert.ToInt32会调用您传入的对象上的IConvertible接口。对于像doubleBigInteger这样的类型,这是实现的,并将对象转换为int,正如您所期望的那样。

as关键字执行强制转换; 如果强制转换失败,则返回null。这仅在对象已经是int的情况下才有效,而不仅仅是可以转换为int的类型。例如:

double d = 1.0;
object o = d;
int? i1 = o as int?; // results in null
int i2 = (int)d; // works
int i3 = Convert.ToInt32(o); //works
int i4 = Convert.ToInt32(d); //works
int i5 = (int)o; // throws an exception at run time

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