我经常发现自己需要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;


还是编译器读取它的方式不同?

编辑

完全清楚地说,由于这里存在可理解和合理的关注点,因此我并不是在编写非常依赖性能的代码。这只是理论上的好奇。更不用说,我宁愿知道我为提高可读性而付出的性能牺牲,而不是盲目地这样做,即使我每次都会花时间。

最佳答案

从技术上讲,使用asis加上强制转换更具性能。总发生的操作较少。

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

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

关于c# - “作为”与"is"在一起,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/24815235/

10-15 09:23