转换:(NewType)与Object作为NewType

时间:2008-08-05 15:42:30

标签: c# .net

  

可能重复:
  Casting vs using the 'as' keyword in the CLR

这两个演员之间究竟有什么区别?

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

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

12 个答案:

答案 0 :(得分:84)

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

[编辑]

我原来的答案肯定是最显着的差异,但正如Eric Lippert points out,它不是唯一的。其他差异包括:

  • 您不能使用'as'运算符强制转换为不接受'null'作为值的类型
  • 你不能使用'as'来转换的东西,比如数字到不同的表示形式(例如,浮动到int)。

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

答案 1 :(得分:27)

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

一起使用

即:

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

不会编译

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

将编译。

答案 2 :(得分:11)

使用“as”进行类型转换当然会在演员失败时更快,因为它避免了抛出异常的费用。

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

底线是:

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

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

答案 3 :(得分:5)

两种方法的区别在于第一种((SomeClass)obj)可能会导致调用type converter

答案 4 :(得分: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。

答案 5 :(得分:4)

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

不要滥用它。 99%的情况下直接投射算子更好。

答案 6 :(得分:3)

要展开Rytmis's comment,您不能将用作关键字用于结构(值类型),因为它们没有空值。

答案 7 :(得分:2)

所有这些都适用于引用类型,值类型不能使用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的实例,那么请使用强制转换。

在.Net 2或更高版本中,泛型意味着你很少需要一个非类型化的引用类实例,所以后者的使用频率较低。

答案 8 :(得分:1)

如果转换尝试失败,则括号转换会抛出异常。如果转换尝试失败,“as”强制转换将返回null。

答案 9 :(得分:1)

他们会抛出不同的例外。
():NullReferenceException
as:InvalidCastException
这有助于调试。

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

“仅使用C#”作为“关键字,你希望演员在非特殊情况下失败。如果你指望一个演员成功并且没有准备接收任何失败的对象,你应该使用()转换运算符,以便抛出适当且有用的异常。“

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

答案 10 :(得分:1)

这就像Parse和TryParse之间的区别。如果你预期它可能会失败,你可以使用TryParse,但是当你有强烈的保证时,你就不会失败使用Parse。

答案 11 :(得分:1)

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