关于c#:Casting :( NewType)与Object为NewType

Casting: (NewType) vs. Object as NewType

本问题已经有最佳答案,请猛点这里访问。

Possible Duplicate:
Casting vs using the 'as' keyword in the CLR

这两种类型有什么区别?

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

通常,它们都应该显式转换为指定的类型?


如果源类型不能转换为目标类型,则前者将引发异常。后者将导致SC2为空引用,但没有异常。

[编辑]

我最初的回答肯定是最明显的不同,但正如埃里克·利珀特指出的,这不是唯一的一个。其他差异包括:

  • 不能使用"as"运算符强制转换为不接受"null"作为值的类型
  • 不能使用"as"将数字等内容转换为其他表示形式(例如,从float转换为int)。

最后,使用"as"和"cast"操作符,您还会说"我不确定这是否会成功。"


还要注意,只能将as关键字与引用类型或可为空的类型一起使用。

IE:

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

不编译

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

将编译。


当强制转换失败时,使用"as"的类型转换当然要快得多,因为它避免了引发异常的开销。

但当演员成功的时候,速度并不快。http://www.codeproject.com/kb/cs/csharpcasts.aspx上的图表具有误导性,因为它无法解释它所测量的内容。

底线是:

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

  • 如果不知道是否会成功,请使用"as"运算符并测试结果是否为空。


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


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

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


这是一个很好的方法来记住他们中的每一个都遵循的过程,当我试图决定哪一个对我的环境更有利时,我会使用这个过程。

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

下一个应该很容易猜出来

1
DateTime i = value as DateTime;

在第一种情况下,如果无法强制转换值,而在第二种情况下无法强制转换值,则将I设置为空。

因此,在第一种情况下,如果在第二种转换中转换失败,将进行硬停止,随后可能会遇到NullReferenceException。


要扩展Rytmis的注释,不能将as关键字用于结构(值类型),因为它们没有空值。


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

1
2
3
4
5
6
//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

1
2
3
4
5
6
7
8
9
10
11
12
13
//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或更高版本中,泛型意味着您很少需要引用类的非类型化实例,因此后者的使用频率较低。


对于那些有vb.net经验的用户,(type)与directcast相同,"as type"与trycast相同。


这就像是parse和typarse之间的区别。当您期望它可能会失败时,可以使用terparse,但当您有足够的把握它不会失败时,可以使用parse。


他们会抛出不同的异常。():空引用异常as:无效castexception这有助于调试。

"as"关键字尝试强制转换对象,如果强制转换失败,将静默返回空值。如果强制转换失败,()强制转换运算符将立即引发异常。

"仅在您希望强制转换在非异常情况下失败的情况下使用c"as"关键字。"如果您指望强制转换成功,并且不准备接收任何失败的对象,则应使用()强制转换运算符,以便引发适当且有用的异常。"

关于代码示例和进一步的解释:http://blog.nerdbank.net/2008/06/when-not-to-use-c-keyword.html


如果强制转换尝试失败,则插入强制转换将引发异常。如果强制转换尝试失败,"as"强制转换将返回空值。