对于内置值类型,“==”判断的是两个对象的代数“值”是否相等。它会根据需要自动进行必要的类型转换,并根据两个对象的“值”是否相等返回true或者false;Equals则需要“值”和“类型”都一样。
而对于用户定义的值类型(如 struct),如果没有重载“==”操作符,“==”将是不能够使用的。
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
先提供一个自定义类,下面的代码需要用到
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
![ExpandedBlockStart.gif](https://images.cnblogs.com/OutliningIndicators/ExpandedBlockStart.gif)
{
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默认行为也是判断两者是否引用同一对象
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)
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
![ExpandedBlockStart.gif](https://images.cnblogs.com/OutliningIndicators/ExpandedBlockStart.gif)
{
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中再加入以下代码
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
![ExpandedBlockStart.gif](https://images.cnblogs.com/OutliningIndicators/ExpandedBlockStart.gif)
{
// return base.equals(obj);
if ( this .CompareTo(obj) == 0 )
return true ;
else
return true ;
}
这样就可以直接使用Equals方法比较了。程序运行后有个小提示“重写了Object.Equals(object o)但不重写Object.GetHashCode()”,把鼠标放到Circle附近,这个没有在“错误列表”显示,再重写GetHashcode()吧(关于这个暂时不清楚,主要参考书籍,等在查找别的资料后补充)
当然,也可以重载“==”运算符(如果重载了“==”,也需要重载“!=”)
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
![ExpandedBlockStart.gif](https://images.cnblogs.com/OutliningIndicators/ExpandedBlockStart.gif)
{
return obj1.Equals(obj2);
}
public static bool operator != (Circle obj1, Circle obj2)
{
return ! (obj1.Equals(obj2));
}
重写“Equals”不需要实现IComparable也是可以的,不知道为什么要实现,直接重写Equals不就行了?或许书上只是为了说明IComparable这个接口的存在!
最后附上全部代码(其中重写GetHashCode()方法的代码只是为了说明问题)
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
![ExpandedBlockStart.gif](https://images.cnblogs.com/OutliningIndicators/ExpandedBlockStart.gif)
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面向对象编程揭秘》