Tri*_*nko 19 c# performance coding-style readability equality
使用该object.ReferenceEquals方法使用时会有额外的开销((object)obj1 == (object)obj2)吗?
在第一种情况下,将涉及静态方法调用,并且在两种情况下都涉及到对象的某种形式的转换.
即使编译器平衡了那些方法,那么不等式呢?
(object)obj != null
Run Code Online (Sandbox Code Playgroud)
相比于...
!object.ReferenceEquals(obj,null)
Run Code Online (Sandbox Code Playgroud)
我想在某些时候,会在!=运算符内或者应用于ReferenceEquals方法的结果时发生逻辑否定.你怎么看?
还有可读性问题需要考虑.在检查相等性时,ReferenceEquals似乎更清晰,但是对于不平等,可能会错过!前面的内容object.ReferenceEquals,而!=第一个变体中很难忽略.
Kon*_*lph 22
使用object.ReferenceEquals方法是否有额外的开销
不.该方法直接包含最小IL描述来执行引用相等性检查(对于记录:它相当于VB的Is运算符)并且通常由JIT内联(特别是在定位x64时),因此没有开销.
关于可读性:我个人认为它object.ReferenceEquals可能更具可读性(即使是否定形式),因为它明确地表达了它的语义.演员object可能会让一些程序员感到困惑.
我刚刚发现了一篇讨论此事的文章.它更喜欢(object)x == y因为IL足迹较小.它认为这可能有助于X使用这种比较来内联方法.但是(没有任何关于JIT的详细知识,但在逻辑上和直觉上)我认为这是错误的:如果JIT表现得像优化C++编译器,它会在内联调用之后考虑该方法ReferenceEquals,因此(为了内联方法)X)无论哪种方式,内存占用都将完全相同.
也就是说:选择一种方式而不是另一种方式对JIT没有任何影响,从而对性能没有任何影响.
与这里的答案相反,我发现的(object) ==速度比快object.ReferenceEquals。至于速度如何,非常微不足道!
试验台:
我知道您需要引用相等性检查,但是object.Equals(,)在未覆盖其类的类的情况下,我也包括静态方法。
平台:x86;配置:发布版本
class Person {
}
public static void Benchmark(Action method, int iterations = 10000)
{
Stopwatch sw = new Stopwatch();
sw.Start();
for (int i = 0; i < iterations; i++)
method();
sw.Stop();
MsgBox.ShowDialog(sw.Elapsed.TotalMilliseconds.ToString());
}
Run Code Online (Sandbox Code Playgroud)
测试:
Person p1 = new Person();
Person p2 = new Person();
bool b;
Benchmark(() =>
{
b = (object)p1 == (object)p2; //960 ~ 1000ms
b = object.ReferenceEquals(p1, p2); //~ 1250ms
b = object.Equals(p1, p2); //2100ms
b = EqualityComparer<Person>.Default.Equals(p1, p2); //~4000ms
}, 100000000);
Person p1 = new Person();
Person p2 = null;
bool b;
Benchmark(() =>
{
b = (object)p1 == (object)p2; //990 ~ 1000ms
b = object.ReferenceEquals(p1, p2); // 1230 ~ 1260ms
b = object.Equals(p1, p2); //1250 ~ 1300ms
b = EqualityComparer<Person>.Default.Equals(p1, p2); //~3100ms
}, 100000000);
Person p1 = null;
Person p2 = null;
bool b;
Benchmark(() =>
{
b = (object)p1 == (object)p2; //960 ~ 1000ms
b = object.ReferenceEquals(p1, p2); //1260 ~ 1270ms
b = object.Equals(p1, p2); //1180 ~ 1220ms
b = EqualityComparer<Person>.Default.Equals(p1, p2); //~3100ms
}, 100000000);
Person p1 = new Person();
Person p2 = p1;
bool b;
Benchmark(() =>
{
b = (object)p1 == (object)p2; //960 ~ 1000ms
b = object.ReferenceEquals(p1, p2); //1260 ~ 1280ms
b = object.Equals(p1, p2); //1150 ~ 1200ms
b = EqualityComparer<Person>.Default.Equals(p1, p2); //3700 ~ 3800ms
}, 100000000);
Run Code Online (Sandbox Code Playgroud)
object.Equals(,)在ReferenceEquals内部调用,如果它们不相等,它将调用Equals该类的重写虚拟方法,因此您会看到速度差异。
结果在Debug配置上也一致...
如前所述,重点应该放在可读性/意义/揭示意图上。