协慌网

登录 贡献 社区

直接铸造与 “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分配给s ,即使onull

string s = o as string; // 2

分配nulls ,如果o是不是一个string ,或者onull 。因此,您不能将其与值类型一起使用(在这种情况下null否则,将o分配给s

string s = o.ToString(); // 3

如果onull则导致NullReferenceExceptiono是什么类型,都将o.ToString()返回的值s


对于大多数转化,请使用 1 - 简单明了。我倾向于几乎从不使用 2,因为如果某些类型不正确,我通常希望发生异常。我只看到这种返回 null 类型的功能需要使用错误代码(例如,返回 null = 错误,而不是使用异常)的错误设计的库。

3 不是强制转换,而只是方法调用。在需要非字符串对象的字符串表示形式时使用它。

  1. string s = (string)o;绝对应该是另一回事时使用。
  2. string s = o as string;当某件事可能是另一回事时使用。
  3. string s = o.ToString();当您不在乎它是什么但只想使用可用的字符串表示形式时使用。

这实际上取决于您是否知道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。这些往往是更常见,很多难以追查,一旦他们在野外发生了,因为几乎每行取消引用变量,可能会抛出一个。在另一方面,如果你想投的值类型(任何原始的,或结构如日期时间),你必须使用直投 - 将as将无法正常工作。

在转换为字符串的特殊情况下,每个对象都有一个ToString o不为 null,并且您认为ToString方法可以完成您想做的事情,那么您的第三个方法就可以了。