.NET学习之“==”、“Equals”、“IComparable”

  对于内置值类型,“==”判断的是两个对象的代数“值”是否相等。它会根据需要自动进行必要的类型转换,并根据两个对象的“值”是否相等返回true或者false;Equals则需要“值”和“类型”都一样。

  而对于用户定义的值类型(如 struct),如果没有重载“==”操作符,“==”将是不能够使用的。

  int  a  =   5 ;
 
int  b  =   5 ;
 Console.WriteLine(
" 值类型,同值同类型: "   +  (a  ==  b)); // True
 Console.WriteLine( " 值类型,同值同类型: "   +  a.Equals(b)); // True

 
int  va  =   1 ;
 
double  vb  =   1 ;
 Console.WriteLine(
" 值类型,同值不同类型: "   +  (va  ==  vb)); // True
 Console.WriteLine( " 值类型,同值不同类型: "   +  va.Equals(vb)); // False

 

先提供一个自定义类,下面的代码需要用到

ExpandedBlockStart.gif 类Circle
class  CircleCenter
    {
        
public   int  X;
        
public   int  Y;
        
public  CircleCenter()
        {

        }
        
public  CircleCenter( int  x, int  y)
        {
            X 
=  x;
            Y 
=  y;
        }
    }
    
class  circle
    {
        
public   double  radius  =   0 ;
        
public  circlecenter center  =   new  circlecenter();
    }

 

   对于引用类型,“==”默认行为是看两个对象是否引用同一对象,但是.NET Framework中的类很多对“==”进行了重载,例如String类的==与Equals的行为相同,判断两个字符串的内容是否相等。所以在应用中,对于系统定义的引用类型建议不要使用==操作符,以免程序出现与预期不同的运行结果。
  Equals默认行为也是判断两者是否引用同一对象

Circle aa  =   new  Circle();
 aa.Radius 
=   10 ;
对象的相互复制不会导致对象自身被复制,其结果是两个对象变量指向同一个对象,
 Circle bb 
=  aa; 
 Circle cc 
=   new  Circle();
 Console.WriteLine(
" bb.Radius: "   +  bb.Radius);  // 10
 bb.Radius  =   15 ;
 cc.Radius 
=   15 ;
 Console.WriteLine(
" aa.Radius: "   +  aa.Radius);  // 15

 Console.WriteLine(aa 
==  cc);  // 引用类型 False
 Console.WriteLine(aa.Equals(cc));  // 引用类型 False
 Console.WriteLine(aa.Radius  ==  cc.Radius);  // 值类型 True
 Console.WriteLine(aa.Radius.Equals(cc.Radius));  // 值类型 True

 Console.WriteLine(
" aa == bb: "   +  (aa  ==  bb)); // True
 Console.WriteLine( " aa.Equals(bb): "   +  aa.Equals(bb)); // True
 Console.WriteLine( " aa.Radius == bb.Radius: "   +  (aa.Radius  ==  b.Radius)); // True
 Console.WriteLine( " aa.Radius.Equals(bb.Radius): " +  aa.Radius.Equals(bb.Radius)); // True

 

  对于一些自定义的类有时候是需要比较的,比方说平面几何中的圆,只要半径是相等的就可以认为是相等的,但默认的“==”和“Equals”均是不行的。

  .NET Framework基础类为两个对象的比较提供了IComparable接口,其含义是:实现了IComparable接口的对象即可相互比较,该接口只定义了一个公共方法int Compareto(object obj)

ExpandedBlockStart.gif 实现了IComparable接口的Circle
class  Circle:IComparable
    {
        
public   double  Radius  =   0 ;
        
public  CircleCenter center  =   new  CircleCenter();

        
#region  IComparable 成员

        
public   int  CompareTo( object  obj)
        {
            
// throw new NotImplementedException();
             if  ( ! (obj  is  Circle))
            {
                
throw   new  ArgumentException( " 只能对比Circle对象 " );
            }
            
if  ((obj  as  Circle).Radius  ==   this .Radius)
            {
                
return   1 ;
            }
            
else
            {
                
return   0 ;
            }
        }

        
#endregion         
    }

  这样就可以用aa.CompareTo(cc) 就是相等的,因为半径是一样的。不过习惯了使用Equals比较,这个不太顺手,在重写Equals方法吧,在上述Circle中再加入以下代码

ExpandedBlockStart.gif 重写Equals方法
  public   override   bool  Equals( object  obj)
        {
            
// return base.equals(obj);
             if  ( this .CompareTo(obj)  ==   0 )
                
return   true ;
            
else
                
return   true ;
        }

   这样就可以直接使用Equals方法比较了。程序运行后有个小提示“重写了Object.Equals(object o)但不重写Object.GetHashCode()”,把鼠标放到Circle附近,这个没有在“错误列表”显示,再重写GetHashcode()吧(关于这个暂时不清楚,主要参考书籍,等在查找别的资料后补充)

  当然,也可以重载“==”运算符(如果重载了“==”,也需要重载“!=”)

ExpandedBlockStart.gif 重载“==”“!=”
  public   static   bool   operator   == (Circle obj1, Circle obj2)
        {
            
return  obj1.Equals(obj2);
        }
        
public   static   bool   operator   != (Circle obj1, Circle obj2)
        {
            
return   ! (obj1.Equals(obj2));
        }

  重写“Equals”不需要实现IComparable也是可以的,不知道为什么要实现,直接重写Equals不就行了?或许书上只是为了说明IComparable这个接口的存在!

  最后附上全部代码(其中重写GetHashCode()方法的代码只是为了说明问题)

ExpandedBlockStart.gif 完整代码
using  System;
using  System.Collections.Generic;
using  System.Linq;
using  System.Text;

namespace  ConsoleApplication7
{
    
class  CustomEqual
    {             
        
static   void  Main()
        {
            
int  a  =   5 ;
            
int  b  =   5 ;
            Console.WriteLine(
" 值类型,同值同类型: "   +  (a  ==  b));
            Console.WriteLine(
" 值类型,同值同类型: "   +  a.Equals(b));
            Console.WriteLine(
"" );

            
int  va  =   1 ;
            
double  vb  =   1 ;            
            Console.WriteLine(
" 值类型,同值不同类型: "   +  (va  ==  vb));
            Console.WriteLine(
" 值类型,同值不同类型: "   +  va.Equals(vb));

            Circle aa 
=   new  Circle();
            aa.Radius 
=   10 ;
            aa.center 
=   new  CircleCenter( 10 10 );

            Circle bb 
=  aa; 
         
            Console.WriteLine(
" bb.Radius: "   +  bb.Radius);
            bb.Radius 
=   15 ;
            Console.WriteLine(
" aa.Radius: "   +  aa.Radius);

            Circle cc 
=   new  Circle();
            cc.Radius 
=   15 ;
            cc.center 
=   new  CircleCenter( 10 10 );           

            Console.WriteLine(
"" );
            Console.WriteLine(
" aa == bb: "   +  (aa  ==  bb));
            Console.WriteLine(
" aa.Equals(bb): "   +  aa.Equals(bb));
            Console.WriteLine(
" aa.Radius == bb.Radius: "   +  (aa.Radius  ==  bb.Radius));
            Console.WriteLine(
" aa.Radius.Equals(bb.Radius): " +  aa.Radius.Equals(bb.Radius));

            Console.WriteLine(
"" );
            Console.WriteLine(
" aa == cc : "   +  (aa  ==  cc));
            Console.WriteLine(
" aa.Equals(cc): "   +  aa.Equals(cc));
            Console.WriteLine(
" aa.Radius == cc.Radius: "   +  (aa.Radius  ==  cc.Radius));
            Console.WriteLine(
" aa.Radius.Equals(cc.Radius): "   +  aa.Radius.Equals(cc.Radius));
            Console.WriteLine(
" aa.center == cc.center : "   +  (aa.center  ==  cc.center));
            Console.WriteLine(
" aa.center.Equals(cc.center): "   +  aa.center.Equals(cc.center));
                   
            Console.ReadKey();
        }
    }

    
class  CircleCenter
    {
        
public   int  X;
        
public   int  Y;
        
public  CircleCenter()
        {

        }
        
public  CircleCenter( int  x, int  y)
        {
            X 
=  x;
            Y 
=  y;
        }
    }
    
// class circle
    
// {
    
//     public double radius = 0;
    
//     public circlecenter center = new circlecenter();
    
// }

    
class  Circle:IComparable
    {
        
public   double  Radius  =   0 ;
        
public  CircleCenter center  =   new  CircleCenter();

        
#region  IComparable 成员

        
public   int  CompareTo( object  obj)
        {
            
// throw new NotImplementedException();
             if  ( ! (obj  is  Circle))
            {
                
throw   new  ArgumentException( " 只能对比Circle对象 " );
            }
            
if  ((obj  as  Circle).Radius  ==   this .Radius)
            {
                
return   1 ;
            }
            
else
            {
                
return   0 ;
            }
        }

        
#endregion

        
public   override   bool  Equals( object  obj)
        {
            
// return base.equals(obj);
             if  ( this .CompareTo(obj)  ==   0 )
                
return   true ;
            
else
                
return   true ;
        }

        
public   static   bool   operator   == (Circle obj1, Circle obj2)
        {
            
return  obj1.Equals(obj2);
        }
        
public   static   bool   operator   != (Circle obj1, Circle obj2)
        {
            
return   ! (obj1.Equals(obj2));
        }

        
public   override   int  GetHashCode()
        {
            
return  ( int )Radius;
            
// return base.GetHashCode();
        }
    }
}

 

  参考网址:http://www.cnblogs.com/Dlonghow/archive/2008/08/04/1259732.html

  参考书籍:金旭亮的《.NET 2.0面向对象编程揭秘》

转载于:https://www.cnblogs.com/hsrzyn/archive/2009/12/17/1626668.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值