本文给大家深度分析讲解一个判等的问题:
object s = 1, t = 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 s = 1, t = 1;
这里,我们看到给两个object变量做了初始化,其中伴随着装箱操作,
所谓装箱,简单地说,就是把值类型转换成引用类型的操作——object:引用类型,int:值类型
我们知道,对于值类型(Int32是值类型)的判等,是二进制的按位判等; 而对引用类型(object是引用类型)的判等,默认为判断两者内存地址是否一致。 这里的object对象,s和t分别初始化,所以地址定然不一致 可以是用object.ReferenceEquals方法验证一下:
Console.WriteLine( "ReferenceEquals(s, t) -> {0}", object.ReferenceEquals( s, t ) );
// 运行结果: // ReferenceEquals(s, t) -> False
相比而言,后面的表达式s.Equals(t)就会复杂一些 我查看了object.Equals( object )这个方法的代码(用的Reflector): public virtual bool Equals( object obj )
{ return RuntimeHelpers.Equals( this, obj ); }
再去查看了RuntimeHelpers.Equals( object, object )的代码,最后发现这是个CLR实现的方法,没有代码··· 仔细想想,关键不在RuntimeHelpers.Equals, 而在这个virtual 对了,这是个虚方法,Int32类型必然会重写这个Equals方法。也就是说,在程序中,实际调用的应该是Int32.Equals
再看Int32的Equals方法,结果就明朗了 public override bool Equals( object obj )
{ return ( (obj is int) && ( this == ( (int) obj ) ) ); }
在这里,s和t都被转换成int类型,再做值类型的按位比较,结果当然是1等于1,返回True (责任编辑:admin) |