直接投射vs'as'运营商?
考虑下面的代码:
void Handler(object o, EventArgs e)
{
// I swear o is a string
string s = (string)o; // 1
//-OR-
string s = o as string; // 2
// -OR-
string s = o.ToString(); // 3
}
这三种类型的铸造之间有什么区别(好吧,第三种不是铸造,但你有意图)。 哪一个应该是首选?
string s = (string)o; // 1
如果o
不是string
则引发InvalidCastException。 否则,即使o
为null
,也将o
赋给s
。
string s = o as string; // 2
分配null
到s
,如果o
是不是一个string
,或者o
为null
。 出于这个原因,你不能将它与值类型一起使用(在这种情况下,操作符永远不能返回null
)。 否则,将o
赋给s
。
string s = o.ToString(); // 3
如果o
为null
则会导致NullReferenceException。 无论o
是什么类型,都将o.ToString()
返回给s
。
使用1进行大多数转换 - 这很简单直接。 我倾向于几乎从不使用2,因为如果事情不是正确的类型,我通常会期望发生异常。 我只看到需要使用错误代码的糟糕设计库(例如,返回null =错误,而不是使用例外)的返回null类型的功能。
3不是强制转换,只是一个方法调用。 在需要非字符串对象的字符串表示时使用它。
这实际上取决于你是否知道o
是一个字符串,以及你想要做什么。 如果你的评论意味着o
真的是一个字符串,我宁愿直接(string)o
投射 - 它不可能失败。
使用直接转换的最大优点是,当它失败时,会得到一个InvalidCastException,它几乎告诉你出了什么问题。
使用as
运算符,如果o
不是字符串,则s
设置为null
,如果您不确定并且想要测试s
,那么这很方便:
string s = o as string;
if ( s == null )
{
// well that's not good!
gotoPlanB();
}
但是,如果您不执行该测试,则稍后将使用s
并引发NullReferenceException。 由于几乎每条线都将一个变量解除引用并可能抛出一个变量,因此这些变量往往更常见,并且一旦发生在野外就很难追查到。 另一方面,如果你试图转换为值类型(任何原始类型或诸如DateTime之类的结构),则必须使用直接投射 - 这as
行不通的。
在转换为字符串的特殊情况下,每个对象都有一个ToString
,所以如果o
不为null,并且您认为ToString
方法可以做到您想要的,则您的第三个方法可能没问题。