我一直在查看.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
做了一些简单的测试,而不是创建一个局部变量,而后者似乎总能产生更好的性能。这种方式不适用于基本类型吗?并且,如果不是,那么假设这是正确的,因为这是一种基本方法,它可能在算法中被调用数百万次,因此性能应该是最重要的?
答案 0 :(得分:2)
假设您只是在没有任何防御性代码的情况下施放值:
public override bool Equals(Object obj)
{
return m_value == ((Int32)obj).m_value;
}
由于Equals
可以使用object
,因此我们不仅应该传递int
值,还应传递float
,string
或几乎任何类型。更糟糕的是,编译器不会抱怨,因为事实上,无论如何它们都只是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
属于不同类型的情况可以通过这种方法直接跳过。