.net类型对象相等分析

这几天,在网上搜索了一些关于判断对象相等的资料,很多,很杂,东云云,西云云,甚至连CSDN,策了半天,都没策出个名堂出来。

实践出真理,于是,我自己写了一些简单的,但有共性的东西,来探个究竟。

例一,目标是对值类型的判断。

(先暂时不考虑用户结构(struct)的判断,因为用户结构需要重写Equals方法,而重写Equals方法是头疼的,一般用户结构都不会重写Equals方法)

int str = 1;

            int str2 = 1;

 

            Console.WriteLine(str == str2);//true    

            Console.WriteLine(str.Equals(str2));//true            Console.WriteLine(Object.Equals(str, str2));//true                Console.WriteLine(Object.ReferenceEquals(str, str2));//false       Console.WriteLine("------------");

 

            int btr = 1;

            int btr2 = 2;

 

            Console.WriteLine(btr == btr2);//false             

            Console.WriteLine(btr.Equals(btr2));//false        

            Console.WriteLine(Object.Equals(btr, btr2));//false

            Console.WriteLine(Object.ReferenceEquals(btr, btr2));//false

        Console.WriteLine("------------");

输出结果;

从输出结果中,可以看到只有Object.ReferenceEquals(Object obj, Object obj)方法,不管值类型的字段是否相等,结果都输出为False,所以可以肯定的是;

一;Object.ReferenceEquals(Object obj, Object obj)方法永远输出False,不管值类型的字段是否相等。(因为值类型经过boxing之后,变成引用类型对象;而此时,值类型的字段已经不是保存的ab,而是类对象的指针,即C++的指针,而这两个指针不相等)

二;“==”,”Int32.Equals(Object obj)”, ”Object.Equals(Object obj,Object obj)”,这三个方法,如果值类型的字段相等,那么都输出True;反之,输出False

三;总结,对于值类型而言,比较对象是否相等,建议使用“==“,而不使用Equals方法,因为使用Equals方法需要boxing,boxing是很耗内存和CPU的,完全是画蛇添足。

四,你如果怀疑Int32不能代表全部的值类型,可以试试其他类型,byte,float等,哈哈!

              例二,目标是对引用类型的判断。

(暂不考虑System.String类型,因为String有他的特性)

情景一

//如果sb=”a”,sb2=”a”

 

             StringBuilder sb = new StringBuilder("a");

            StringBuilder sb2 = new StringBuilder("a");

            Object sb3 = sb2;

 

Console.WriteLine(sb == sb2);//false            Console.WriteLine(sb.Equals(sb2));//true

Console.WriteLine(Object.Equals(sb, sb2));//false                  Console.WriteLine(Object.Equals(sb2, sb3));//true                      Console.WriteLine(Object.ReferenceEquals(sb, sb2));//false              Console.WriteLine(Object.ReferenceEquals(sb2, sb3));//true   

Console.WriteLine(sb2 == sb3);// true 

Console.WriteLine(sb2.Equals(sb3));//true 

Console.WriteLine(Object.Equals(sb2, sb3));// true Console.WriteLine("------------");

         情景二

         //如果bsb =”a”, bsb2 =”b”

            StringBuilder bsb = new StringBuilder("a");

            StringBuilder bsb2 = new StringBuilder("b");

            Object bsb3 = bsb2;

 

     Console.WriteLine(bsb == bsb2);//false 

Console.WriteLine(bsb.Equals(bsb2));//false            Console.WriteLine(Object.Equals(bsb, bsb2));//false               Console.WriteLine(Object.Equals(bsb2, bsb3));//true             Console.WriteLine(Object.ReferenceEquals(bsb, bsb2));//false              Console.WriteLine(Object.ReferenceEquals(bsb2, bsb3));//true  

Console.WriteLine(bsb2 == bsb3);//true            Console.WriteLine(bsb2.Equals(bsb3));//true               Console.WriteLine(Object.Equals(bsb2, bsb3));//true 

Console.WriteLine("------------");

         输出结果

        

从输出结果可以看到倒数四个项输出都为True,为什么呢?因为Object sb3 = sb2Object bsb3 = bsb2中的sb2bsb2都是把自己的指针传递给目标sb3sb2,都指向堆中的同一块内存。

再看,倒数第五项,都输出为False,因为Object.ReferenceEqualsObject obj,Object obj)方法比较的是对象的引用,即同一性。

再看倒数第六项和第七项,都输出为TrueFalse,因为Object.Equals(Object ojb, Object obj),比较的也是对象的引用。

再看倒数第九项,都输出为False,因为==操作对引用类型而言,比较的是引用。

最后,来看看倒数第八项,sb.Equals(sb2)bsb.Equals(bsb2),为什么我要放在最后说呢?因为这个方法比较特殊,他是具体类型的方法,(不同于System.Object.Equals(Object obj)方法)。用反射的方法,可以很容易的看到sb.Equals(sb2)的实现,如下;

public bool Equals(StringBuilder sb)
{
    if ((sb != null) && ((this.Capacity == sb.Capacity) && (this.MaxCapacity == sb.MaxCapacity)))
    {
        return this.m_StringValue.Equals((string) sb.m_StringValue);
    }
    return false;
}
再看看祖宗的System.Object.Equals(Ojbect obj)是怎样实现的,如下;
public virtual bool Equals(object obj)
{
    return InternalEquals(this, obj);
}
奇怪?InternalEquals(this, obj)的实行是啥呢?去看看;
[MethodImpl(MethodImplOptions.InternalCall)]
internal static extern bool InternalEquals(object objA, object objB);
InternalEquals方法根本没有实现
    
    
可以看到每个具体类型的Equals()方法,都可能有不同的实现;所以,在判断引用类型是否相等的时候,要避免使用他们自己的Equals()方法,因为可能实现都不同,也有可能他娘的根本没实现,所以建议使用祖宗System.Object.ReferenceEquals(Object, Object)方法。
   
   

如果不信可以把StringBuilder bsb = new StringBuilder("a")改成Object bsb = new Object();bsb.Equals()输出结果不同。

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值