我经常发现自己需要switch
种类型。我知道这有很多关于Roslyn的讨论,但是由于我处理的是生产代码,我只是对已经存在的选项有一个标准的练习/性能问题:is
和as
。
鉴于课程,
abstract class Foo { }
class Bar : Foo { }
class Tada : Foo { }
以下模式之间是否有任何真正的区别?
Foo toUse = ...;
if (toUse != null)
{
Bar barInstance = toUse as Bar;
if (barInstance != null)
{
// use barInstance
}
else
{
Tada tadaInstance = toUse as Tada;
if (tadaInstance != null)
{
// use tadaInstance
}
else
{
// Check whatever other types there are, or throw a NotImplementedException
}
}
}
else
{
// handle the null case
}
与
相比Foo toUse = ...;
if (toUse != null)
{
Bar barInstance = toUse as Bar;
if (toUse is Bar)
{
Bar barInstance = (Bar)toUse;
// use barInstance
}
else if (toUse is Tada)
{
Tada tadaInstance = (Tada)toUse;
// use tadaInstance
}
else
{
// Check whatever other types there are, or throw a NotImplementedException
}
}
else
{
// handle the null value
}
很明显,错别字允许,这两个具有相同的影响。他们应该做同样的事情。但这里有性能问题吗?我总是很欣赏第一种模式的单一操作性质,但它太乱了。更不用说,它将所有内容都放在了范围内,这样你就可以了解更多的设置,包括更多的案例。
as
真的只是一个语法快捷方式吗?
if (value is type)
return (type)value;
else
return null;
或者编译器读取它的方式有所不同吗?
修改
只是非常清楚,因为这里有可理解和合理的关注,我不会编写需要依赖性能的代码。这只是理论上的好奇心。更不用说了,我更愿意意识到我为可读性做出的性能牺牲,而不是盲目地做,尽管我每次都会接受它。
答案 0 :(得分:8)
使用as
在技术上比is
加上强制转换更高效。发生的总操作较少。
出于实际目的,速度差异在现实世界中几乎无法衡量,因此在您的情况下使用更易于维护/可读的版本会更好。
但是,对类型进行大量检查通常是设计问题的一个标志。您可能需要考虑重新考虑您的设计以完全阻止检查。泛型或虚方法调用通常可以完全消除对此类检查的需要。
答案 1 :(得分:2)
还有一点要指出的是,当你喜欢下面的时候
Bar barInstance = toUse as Bar;
始终建议您在使用barInstance
之前检查是否无效。
if (barInstance != null)
{
// use barInstance
}
如果演员失败你会得到正确的异常细节,如果你说(Bar)toUse
并且没有检查无效,你将会解决原始异常并结束面临toUse as Bar
例外。