"如"对比"是"随着演员

时间:2014-07-17 23:35:57

标签: c# performance casting

我经常发现自己需要switch种类型。我知道这有很多关于Roslyn的讨论,但是由于我处理的是生产代码,我只是对已经存在的选项有一个标准的练习/性能问题:isas

鉴于课程,

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;

或者编译器读取它的方式有所不同吗?

修改

只是非常清楚,因为这里有可理解和合理的关注,我不会编写需要依赖性能的代码。这只是理论上的好奇心。更不用说了,我更愿意意识到我为可读性做出的性能牺牲,而不是盲目地做,尽管我每次都会接受它。

2 个答案:

答案 0 :(得分:8)

使用as在技术上比is加上强制转换更高效。发生的总操作较少。

出于实际目的,速度差异在现实世界中几乎无法衡量,因此在您的情况下使用更易于维护/可读的版本会更好。

但是,对类型进行大量检查通常是设计问题的一个标志。您可能需要考虑重新考虑您的设计以完全阻止检查。泛型或虚方法调用通常可以完全消除对此类检查的需要。

答案 1 :(得分:2)

还有一点要指出的是,当你喜欢下面的时候

Bar barInstance = toUse as Bar;

始终建议您在使用barInstance之前检查是否无效。

if (barInstance != null)
{
    // use barInstance
}

如果演员失败你会得到正确的异常细节,如果你说(Bar)toUse并且没有检查无效,你将会解决原始异常并结束面临toUse as Bar例外。