考虑以下代码:

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 = o as string; // 2

首选,因为它避免了双重铸造的性能损失。

其他回答

根据本页上运行的实验: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是一组类型之一,本质上是框架基类型。

如果您已经知道它可以转换为什么类型,请使用C样式转换:

var o = (string) iKnowThisIsAString; 

注意,只有使用C样式转换才能执行显式类型强制。

如果您不知道它是否是所需的类型,如果是,您将使用它,请使用关键字:

var s = o as string;
if (s != null) return s.Replace("_","-");

//or for early return:
if (s==null) return;

注意,as不会调用任何类型转换运算符。仅当对象不为空且本机为指定类型时,它才为非空。

使用ToString()获取任何对象的可读字符串表示,即使它不能转换为字符串。

string s = (string)o; // 1

如果o不是字符串,则引发InvalidCastException。否则,将o赋给s,即使o为空。

string s = o as string; // 2

如果o不是字符串或o为空,则将null赋给s。因此,不能将其用于值类型(在这种情况下,运算符永远不会返回null)。否则,将o指定给s。

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

如果o为空,则导致NullReferenceException。无论o是什么类型,都将任何o赋值给ToString()返回的值。


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

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

2可用于转换为派生类型。

假设a是动物:

b = a as Badger;
c = a as Cow;

if (b != null)
   b.EatSnails();
else if (c != null)
   c.EatGrass();

将得到最少的投喂。