为什么C#的基本类型'等于实施演员两次?

时间:2015-11-12 13:51:38

标签: c# performance

我一直在查看.NET的参考源,例如Int32的Equals实现,如下所示:

public override bool Equals(Object obj) {
    if (!(obj is Int32)) {
        return false;
    }
    return m_value == ((Int32)obj).m_value;
}

我已经查找了Char和Bool,他们都做了同样的事情。

来源:http://referencesource.microsoft.com/mscorlib/R/13ad4f778352f7c4.html

然而,这违反了CA1800: Do not cast unnecessarily

此外,我已经使用is做了一些简单的测试,而不是创建一个局部变量,而后者似乎总能产生更好的性能。这种方式不适用于基本类型吗?并且,如果不是,那么假设这是正确的,因为这是一种基本方法,它可能在算法中被调用数百万次,因此性能应该是最重要的?

2 个答案:

答案 0 :(得分:2)

假设您只是在没有任何防御性代码的情况下施放值:

public override bool Equals(Object obj)
{
     return m_value == ((Int32)obj).m_value;
}

由于Equals可以使用object,因此我们不仅应该传递int值,还应传递floatstring或几乎任何类型。更糟糕的是,编译器不会抱怨,因为事实上,无论如何它们都只是objects,所以这个电话是完全合法的。

但如果你将string投放到int会怎样?我们在运行时得到InvalidCastException,这根本不好。

因此,在将object投射到int之前,我们必须检查int实际上是is,这就是return obj is Int32 ? m_value == ((Int32)obj).m_value : false; 关键字的作用。< / p>

作为旁注,方法体也可以写成:

#include <iostream>

struct A { 
    int i; 
};

#ifndef UNSCREW_CLANG
using cast_type = const A;
#else 
using cast_type = A;
#endif

struct B {
    operator cast_type () const {
        return A{i};
    }
    int i;
}; 

int main () { 
    A a{0};
    B b{1};

#ifndef CLANG_WORKAROUND
    a = b;
#else    
    a = b.operator cast_type ();
#endif    

    std::cout << a.i << std::endl;    

    return EXIT_SUCCESS;
}

答案 1 :(得分:0)

is运算符用于检查obj的类型 如果obj与您投射的类型不同,则直接投射可能会导致异常(在本例中为Int32)。
为防止此潜在异常,请使用is obj属于不同类型的情况可以通过这种方法直接跳过。