一个简单判等例子的深度分析
2011-01-23 23:12 贼寇在何方 阅读(1664) 评论(1) 编辑 收藏 举报今儿给网友讲解了一个判等的问题,看似简单,其实还是蛮有意思的:
Console.WriteLine( "s == t -> {0}", s == t );
Console.WriteLine( "s.Equals(t) -> {0}", s.Equals( t ) );
// 运行结果:
// s == t -> False
// s.Equals(t) -> True
这个结果可能会让不少同学觉得意外,那我就来给大家分析下
这里,我们看到给两个object变量做了初始化,其中伴随着装箱操作,
所谓装箱,简单地说,就是把值类型转换成引用类型的操作——object:引用类型,int:值类型
详细的可以看这篇文章:C# 装箱和拆箱
我们知道,对于值类型(Int32是值类型)的判等,是二进制的按位判等; 而对引用类型(object是引用类型)的判等,默认为判断两者内存地址是否一致。
这里的object对象,s和t分别初始化,所以地址定然不一致
可以是用object.ReferenceEquals方法验证一下:
// 运行结果:
// ReferenceEquals(s, t) -> False
结果得到证实,所以 s == t自然就False了
相比而言,后面的表达式s.Equals(t)就会复杂一些
我查看了object.Equals( object )这个方法的代码(用的Reflector):
{
return RuntimeHelpers.Equals( this, obj );
}
再去查看了RuntimeHelpers.Equals( object, object )的代码,最后发现这是个CLR实现的方法,没有代码···
仔细想想,关键不在RuntimeHelpers.Equals, 而在这个virtual
对了,这是个虚方法,Int32类型必然会重写这个Equals方法。也就是说,在程序中,实际调用的应该是Int32.Equals
再看Int32的Equals方法,结果就明朗了
{
return ( (obj is int) && ( this == ( (int) obj ) ) );
}
在这里,s和t都被转换成int类型,再做值类型的按位比较,结果当然是1等于1,返回True
参考: