.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

 

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

类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)

实现了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中再加入以下代码

重写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()吧(关于这个暂时不清楚,主要参考书籍,等在查找别的资料后补充)

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

重载“==”“!=”
 public static bool perator ==(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()方法的代码只是为了说明问题)

完整代码
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 perator ==(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();
        }
    }
}

 

来自 “ ITPUB博客 ” ,链接:http://blog.itpub.net/12639172/viewspace-622785/,如需转载,请注明出处,否则将追究法律责任。

转载于:http://blog.itpub.net/12639172/viewspace-622785/

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值