90

这两个演员阵容之间实际上有什么区别?

SomeClass sc = (SomeClass)SomeObject;
SomeClass sc2 = SomeObject as SomeClass;

通常,它们不应该都是对指定类型的显式强制转换吗?

4

12 回答 12

88

如果源类型不能转换为目标类型,前者会抛出异常。后者将导致 sc2 为空引用,但也不例外。

[编辑]

我最初的答案当然是最明显的区别,但正如 Eric Lippert指出的那样,它不是唯一的。其他差异包括:

  • 您不能使用“as”运算符强制转换为不接受“null”作为值的类型
  • 您不能使用“as”来转换事物,例如将数字转换为不同的表示形式(例如,将浮点数转换为整数)。

最后,使用 'as' 与 cast 操作符,你也在说“我不确定这是否会成功”。

于 2008-08-05T15:44:46.330 回答
27

另请注意,您只能将 as 关键字与引用类型或可为空的类型一起使用

IE:

double d = 5.34;
int i = d as int;

不会编译

double d = 5.34;
int i = (int)d;

将编译。

于 2008-08-05T16:15:38.437 回答
11

当转换失败时,使用“as”进行类型转换当然要快得多,因为它避免了抛出异常的代价。

但是当演员成功时,它并没有更快。http://www.codeproject.com/KB/cs/csharpcasts.aspx上的图表具有误导性,因为它没有解释测量的内容。

底线是:

  • 如果您希望演员表成功(即失败是例外),请使用演员表。

  • 如果您不知道它是否会成功,请使用“as”运算符并测试结果是否为 null。

于 2008-09-16T19:21:21.680 回答
5

这两种方法的区别在于第一个 ((SomeClass)obj) 可能会导致调用类型转换器

于 2008-11-07T23:46:49.017 回答
5

好吧,'as' 运算符“帮助”你把你的问题埋得更低,因为当它被提供一个不兼容的实例时,它会返回 null,也许你会将它传递给一个方法,该方法将它传递给另一个方法,依此类推,最后你'会得到一个 NullReferenceException ,这将使您的调试更加困难。

不要滥用它。在 99% 的情况下,直接转换运算符更好。

于 2010-10-28T09:21:44.530 回答
4

这是记住每个人遵循的过程的好方法,我在尝试决定哪个更适合我的情况时使用。

DateTime i = (DateTime)value;
// is like doing
DateTime i = value is DateTime ? value as DateTime : throw new Exception(...);

接下来应该很容易猜到它的作用

DateTime i = value as DateTime;

在第一种情况下,如果无法转换该值,则在第二种情况下,如果无法转换该值,则会引发异常,则将 i 设置为 null。

因此,在第一种情况下,如果在第二次强制转换中失败,则会进行硬停止,然后会进行软停止,稍后您可能会遇到 NullReferenceException。

于 2008-08-05T17:46:00.970 回答
3

要扩展Rytmis 的评论,您不能对结构(值类型)使用as关键字,因为它们没有空值。

于 2008-09-07T08:08:28.067 回答
3

所有这些都适用于引用类型,值类型不能使用as关键字,因为它们不能为空。

//if I know that SomeObject is an instance of SomeClass
SomeClass sc = (SomeClass) someObject;


//if SomeObject *might* be SomeClass
SomeClass sc2 = someObject as SomeClass;

强制转换语法更快,但只有在成功时,失败才会慢得多。

最佳做法是as在您不知道类型时使用:

//we need to know what someObject is
SomeClass sc;
SomeOtherClass soc;

//use as to find the right type
if( ( sc = someObject as SomeClass ) != null ) 
{
    //do something with sc
}
else if ( ( soc = someObject as SomeOtherClass ) != null ) 
{
    //do something with soc
}

但是,如果您绝对确定这someObjectSomeClass然后使用 cast 的一个实例。

在 .Net 2 或更高版本中,泛型意味着您很少需要引用类的无类型实例,因此后者不太常用。

于 2008-09-18T11:10:03.153 回答
2

对于那些有 VB.NET 经验的人,(type) 与 DirectCast 相同,“as type”与 TryCast 相同。

于 2008-09-16T21:55:28.610 回答
1

如果转换尝试失败,括号中的转换将引发异常。如果转换尝试失败,则“as”转换返回 null。

于 2008-08-05T15:45:06.610 回答
1

他们会抛出不同的异常。

():NullReferenceException
作为:InvalidCastException

这可以帮助调试。

“as”关键字尝试转换对象,如果转换失败,则返回 null。如果转换失败, () 转换运算符将立即抛出异常。

仅在您期望强制转换在非异常情况下失败的地方使用 C#“as”关键字。如果您指望强制转换成功并且没有准备好接收任何将失败的对象,则应使用 () 强制转换运算符,以便引发适当且有用的异常。

有关代码示例和进一步说明:http: //blog.nerdbank.net/2008/06/when-not-to-use-c-keyword.html

于 2008-08-05T15:49:34.310 回答
1

这就像 Parse 和 TryParse 之间的区别。当您预计它可能会失败时,您使用 TryParse,但是当您有充分的保证它不会失败时,您使用 Parse。

于 2008-08-08T12:00:01.940 回答