C#相等比较

  C#中的对象都继承自System.Object对象,分为引用类型和值类型两种,所以对象的相等比较而言就分两种,一种是比较引用,一种是比较值。System.Object默认提供了三个方法来进行对象的相等比较:静态的ReferenceEquals()、Equals()静态方法、Equals()虚方法(子类可以去重写)和“==”运算符。

1、静态的ReferenceEquals()
  ReferenceEquals()是一个静态方法,比较两个对象是否引用自同一个地址,是则返回true,否则返回false
  调用方法:ReferenceEquals(obj1,obj2)
  比较原则:
      1)、obj1和obj2同为null,则返回true
      2)、obj1和obj2只有一个为null,则返回false
      3)、obj1和obj2均不为null时,比较两个对象的引用地址,是则返回true,不是则返回false

2、 Equals()虚拟版本
   System.Object实现代码也比较引用。但因为这个方法是虚拟的,所以可以在自己的类中重写它,按值来比较对象。特别是如果希望类的实例用作字典中的键,就需要重写这个方法,以比较值。否则,根据重写Object.GetHashCode()的方式,包含对象的字典类要么不工作,要么工作的效率非常低。在重写Equals()方法时要注意,重写的代码不会抛出异常。这是因为如果抛出异常,字典类就会出问题,一些在内部调用这个方法的.NET基类也可能出问题。

3、静态的Equals()方法
    Equals()的静态版本与其虚拟实例版本的作用相同,其区别是静态版本带有两个参数,并对它们进行相等比较。这个方法可以处理两个对象中有一个是null的情况,因此,如果一个对象可能是null,这个方法就可以抛出异常,提供了额外的保护。静态重载版本首先要检查它传送的引用是否为null。如果它们都是null,就返回true(因为null与null相等)。如果只有一个引用是null,就返回false。 如果两个引用都指向某个对象,它就调用Equals()的虚拟实例版本。这表示在重写Equals()的实例版本时,其效果相当于也重写了静态版本。

4、“==”比较运算符
   在默认情况下,==运算符对引用类型比较的是两个对象指向的引用是否是同一个对象,但是作为一个自定义的复杂类,可以自己重写适合自己的“==”运算符,在重写“==”时必须同时重写“!=”运算符。

特殊注意的是:在重写相等比较时,要小心可能的循环调用问题

  public  class  List <T>
    {
         const  int  defaultCapacity = 4;
        T[] items;
         int  count;

         public  int  Count
        {
             get  {  return  count; }
             private  set  { count =  value ; }
        }

         public  int  Capacity
        {
             get
            {
                 return  items.Length;
            }
             set
            {
                 if  (  value  < count)  value  = count;
                 if  (  value  != items.Length)
                {
                    T[] newItems =  new  T[  value ];
                     Array .Copy(items, 0, newItems, 0, count);
                    items = newItems;
                }
            }

        }

         public  event  EventHandler  Changed;

         public  List(  int  capacity=defaultCapacity)
        {
             this .items=  new  T[capacity];
             this .Capacity = capacity;
             this .count = 0;
        }

         public  T  this [  int  index]
        {
             get
            {
                 return  items[index];
            }
             set
            {
                items[index] =  value ;
                OnChanged();
            }
        }

         public  void  Add(T item)
        {
             if  (count == Capacity) Capacity = count * 2;
            items[count] = item;
            count++;
            OnChanged();
        }


         protected  virtual  void  OnChanged()
        {
             if  (Changed !=  null ) Changed(  this ,  EventArgs .Empty);
        }

         public  override  bool  Equals(  object  other)
        {
             return  Equals(  this , other  as  List <T>);
        }

         public  override  int  GetHashCode()
        {
             return  this .items.GetHashCode();
        }

         static  bool  Equals(  List <T> a,  List <T> b)
        {
             //不能用a==null或((object)a).Equals(null),会导致循环调用,因为它们会通过多态机制,最终调用实例的==或Equals(object other)
             //可以用object.Equals(a,null)或(object)a==null,这会调用object的statice Equals(),这个静态比较方法内部有特殊处理,不进行多态机制的传递过程
             if  (  object .Equals(a,  null ))  return  object .Equals(b,  null );
             if  (  object .Equals(b,  null ) || a.count != b.count)  return  false ;
             for  (  int  i = 0; i < a.count; i++)
            {
                 //通过这个调用元素自身的Equals方法
                 if  (!  object .Equals(a.items[i], b.items[i]))
                {
                     return  false ;
                }
            }
             return  true ;
        }

         public  static  bool  operator  ==(  List <T> a,  List <T> b)
        {
             return  Equals(a, b);
        }

         public  static  bool  operator  !=(  List <T> a,  List <T> b)
        {
             return  !Equals(a, b);
        }
    }
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值