您的位置:首页 > 其它

一个简单判等例子的深度分析

2011-01-23 23:12 281 查看
今儿给网友讲解了一个判等的问题,看似简单,其实还是蛮有意思的:

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:值类型

详细的可以看这篇文章:C# 装箱和拆箱

我们知道,对于值类型(Int32是值类型)的判等,是二进制的按位判等; 而对引用类型(object是引用类型)的判等,默认为判断两者内存地址是否一致。

这里的object对象,s和t分别初始化,所以地址定然不一致

可以是用object.ReferenceEquals方法验证一下:

Console.WriteLine( "ReferenceEquals(s, t) -> {0}", object.ReferenceEquals( s, t ) );

// 运行结果:
// ReferenceEquals(s, t) -> False

结果得到证实,所以 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

参考:

C# 装箱和拆箱

详解.NET中六个你必须知道的重要概念
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: