题
可能的重复:
强制转换与在 CLR 中使用“as”关键字
这两个演员阵容实际上有什么区别?
SomeClass sc = (SomeClass)SomeObject;
SomeClass sc2 = SomeObject as SomeClass;
通常,它们都应该显式转换为指定类型?
解决方案
如果源类型无法转换为目标类型,前者将引发异常。后者将导致 sc2 成为空引用,但也不例外。
[编辑]
我原来的答案当然是最明显的区别,但正如埃里克·利珀特(Eric Lippert) 指出, ,这不是唯一的一个。其他差异包括:
- 您不能使用“as”运算符来转换为不接受“null”作为值的类型
- 你不能使用“as”来 转变 事物,例如数字到不同的表示形式(例如,从浮点到整数)。
最后,使用“as”与“as”演员操作员,你也说“我不确定这是否会成功。”
其他提示
另请注意,只能将 as 关键字与引用类型或可为空类型一起使用
IE:
double d = 5.34;
int i = d as int;
不会编译
double d = 5.34;
int i = (int)d;
将编译。
当转换失败时,使用“as”进行类型转换当然要快得多,因为它避免了抛出异常的代价。
但演员成功后,速度并没有更快。图表位于 http://www.codeproject.com/KB/cs/csharpcasts.aspx 具有误导性,因为它没有解释它所测量的内容。
底线是:
如果您期望演员阵容成功(即失败是例外),使用强制转换。
如果您不知道是否会成功,请使用“as”运算符并测试结果是否为 null。
两种方法之间的区别在于第一个 ((SomeClass)obj) 可能会导致 类型转换器 被称为。
这是一个记住每个过程的好方法,我在尝试决定哪个更适合我的情况时使用它。
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。
出色地 “as”运算符“帮助”您将问题埋得更低 因为当提供一个不兼容的实例时,它将返回 null,也许您会将其传递给一个方法,该方法将其传递给另一个方法,依此类推,最后您将得到一个 NullReferenceException,这将使您的调试更加困难。
不要滥用它。在 99% 的情况下,直接转换运算符更好。
扩展至 里特米斯的评论, ,你不能使用 作为 结构(值类型)的关键字,因为它们没有空值。
所有这些都适用于引用类型,值类型不能使用 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
}
但是,如果您绝对确定 someObject
是一个实例 SomeClass
然后使用演员表。
在 .Net 2 或更高版本中,泛型意味着您很少需要引用类的非类型化实例,因此后者较少使用。
如果强制转换尝试失败,括号中的强制转换将引发异常。如果转换尝试失败,“as”转换将返回 null。
他们会抛出不同的异常。
():空引用异常
作为 :无效转换异常
这可以帮助调试。
“as”关键字尝试强制转换对象,如果强制转换失败,则默默返回 null。如果转换失败,() 转换运算符将立即抛出异常。
“仅当您期望转换在非例外情况下失败时才使用 C#“as”关键字。如果您指望强制转换能够成功,并且没有准备好接收任何失败的对象,则应该使用 () 强制转换运算符,以便抛出适当且有用的异常。”
有关代码示例和进一步说明: http://blog.nerdbank.net/2008/06/when-not-to-use-c-keyword.html
这就像 Parse 和 TryParse 之间的区别。当您预计 TryParse 可能会失败时,您可以使用 TryParse,但是当您有充分的保证它不会失败时,您可以使用 Parse。
对于那些具有 VB.NET 经验的人来说,(type) 与 DirectCast 相同,“as type”与 TryCast 相同。