考虑以下代码:

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
}

三种类型的施法有什么区别(好吧,第三种不是施法,但你明白了意图)。应该首选哪一种?


当前回答

如果我可以补充一下,所有给出的答案都很好:要直接使用字符串的方法和财产(例如ToLower),您不能编写:

(string)o.ToLower(); // won't compile

你只能写:

((string)o).ToLower();

但你可以写:

(o as string).ToLower();

as选项更可读(至少在我看来)。

其他回答

根据本页上运行的实验:http://www.dotnetguru2.org/sebastienros/index.php/2006/02/24/cast_vs_as

(此页面有时会显示一些“非法引用者”错误,因此如果出现,请刷新)

结论是,“as”运算符通常比强制转换快。有时速度快很多倍,有时仅仅快不了几倍。

我个人认为“as”也更可读。

因此,由于它既快又“安全”(不会抛出异常),而且可能更容易阅读,我建议一直使用“as”。

“(string)o”将导致InvalidCastException,因为没有直接强制转换。

“o as string”将导致s为空引用,而不是引发异常。

“o.ToString()”本身并不是任何类型的强制转换,它是一个由对象实现的方法,因此以某种方式由.net中的每个类实现,这些类对它所调用的类的实例“做一些事情”并返回字符串。

不要忘记,对于转换为字符串,还有Convert.ToString(someType instanceOfThatType),其中someType是一组类型之一,本质上是框架基类型。

这真的取决于你是否知道o是否是一个字符串,以及你想用它做什么。如果你的评论意味着o真的是一个串,我更喜欢直接(字符串)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不为空,并且您认为ToString方法可以执行您想要的操作,则第三个方法可能是正确的。

当试图获取任何(任何类型)可能为空的字符串表示时,我更喜欢下面的代码行。它很紧凑,它调用ToString(),并正确处理空值。如果o为空,则s将包含String.Empty。

String s = String.Concat(o);

因为没有人提到它,所以最接近instanceOf的关键字是:

obj.GetType().IsInstanceOfType(otherObj)