可能重复:使用CLR中的'as'关键字进行转换
哪种方法被认为是最佳做法?
先投?
public string Describe(ICola cola)
{
var coke = cola as CocaCola;
if (coke != null)
{
string result;
// some unique coca-cola only code here.
return result;
}
var pepsi = cola as Pepsi;
if (pepsi != null)
{
string result;
// some unique pepsi only code here.
return result;
}
}
或者我应该先检查,然后再投?
public string Describe(ICola cola)
{
if (cola is CocaCola)
{
var coke = (CocaCola) cola;
string result;
// some unique coca-cola only code here.
return result;
}
if (cola is Pepsi)
{
var pepsi = (Pepsi) cola;
string result;
// some unique pepsi only code here.
return result;
}
}
你能看到其他任何方式吗?
5 回答
如果对象可能是您想要的类型,那么
as
运算符(您的第一种方法)在两个方面更好:可读性和易维护性:您只需指定一次类型
表现:你只进行一次施法,而不是两次 . (琐事:当你使用
is
关键字时,C#编译器在内部将其转换为as
,即 .coke is Cola
相当于(coke as Cola) != null
)如果对象应始终是请求的类型,那么只需执行
(Coke)cola
并让它抛出异常,如果不是这样的话 .第一个(第一个通过as)效率稍高,所以在这方面,它可能是最好的做法 .
但是,上面的代码通常会显示一些"code smell" . 如果可能的话,我会考虑重构遵循此模式的任何代码 . 让
ICola
提供一种描述方法,并让它描述自己 . 这避免了类型检查和重复代码......此示例使用一个安全的本地参数,但很多时候将类型检查应用于类的字段(成员变量) . 在这种情况下,“as”-then-check是安全的,但是“is”-then-cast会造成无偿的竞争条件 .
我认为第一种方式更有效:施放然后检查,但......
你为开发人员开发了很多时间,在我看来,首先检查它然后再进行铸造......
让我把它放在那里 . 但我认为两者都不对:)在你的特定例子中,为什么还有一个接口呢?我会在您的ICola接口上放置一个“Describe”方法,然后在实现该接口的CocaCola和Pepsi类中实现describe逻辑 .
所以基本上把
// some unique <some cola> only code here.
放到实现类中 .但是为了回答你的问题,我认为check-then-cast更合适 .