考虑以下代码:
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
}
三种类型的施法有什么区别(好吧,第三种不是施法,但你明白了意图)。应该首选哪一种?
考虑以下代码:
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选项更可读(至少在我看来)。
其他回答
这真的取决于你是否知道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方法可以执行您想要的操作,则第三个方法可能是正确的。
如果您已经知道它可以转换为什么类型,请使用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()获取任何对象的可读字符串表示,即使它不能转换为字符串。
当试图获取任何(任何类型)可能为空的字符串表示时,我更喜欢下面的代码行。它很紧凑,它调用ToString(),并正确处理空值。如果o为空,则s将包含String.Empty。
String s = String.Concat(o);
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不是强制转换,只是方法调用。当您需要非字符串对象的字符串表示时,请使用它。
如果我可以补充一下,所有给出的答案都很好:要直接使用字符串的方法和财产(例如ToLower),您不能编写:
(string)o.ToLower(); // won't compile
你只能写:
((string)o).ToLower();
但你可以写:
(o as string).ToLower();
as选项更可读(至少在我看来)。