之前讲过要重写Equals()就要重写GetHashCode(),这次说一下自己学到的如何重写Equals()。
首先,需要了解 “对象同一性”和“相等的对象”的含义区别
涉及到:相等的值类型、相等的引用类型、同一(相等的引用)
举个最简单的例子,一看便知:
int a=42;
int b=42;
string aa="1";
string bb="1";
string cc=aa;
相信稍微懂点C#的因该知道,int为值类型,string为引用类型。
所以相等的值类型就是说a和b ,,,相等引用类型为aa和bb,,,同一自然就是aa和cc
对象同一指两个引用假如引用同一个实例,即对象同一。可用ReferenceEquals()检查
两个对象实例也可能相等,如果标识它们的值相等,即相等的对象。
这里注意:::值类型本身不可能引用相等。!!
想一下ReferenceEquals()像参数传入同一个值类型,它们会复制到被调用的方法参数中,即装箱而每个实参装入了不同的箱中(即栈的不同位置),所以永远不可能引用相等。
下面说一下实现Equals():
重写步骤大体如下:
1.检查是否为null
2.如果是引用类型,则检查引用是否相等
3.检查数据类型是否相同
4.调用一个指定了具体类型的辅助方法,它能将操作数视为要比较的类型而不是一个对象
5.检查散列码是否相等,若不相等,必须继续执行全面的逐个字段比较
6.如果基类重写Equals,检查base.Equals();
7.比较每个标识字段,判断是否相等
8.重写GetHashCode
9.重写==和!=运算符
下面的例子进行展示
public struct Longitude
{ }
public struct Latitude { }
public struct Coordinate
{
private readonly Latitude _Latitude;
private readonly Longitude _Longitude;
public Longitude Longitude
{
get { return _Longitude; }
}
public Latitude Latitude
{
get { return _Latitude; }
}
public Coordinate(Longitude longitude, Latitude latitude)
{
_Longitude = longitude;
_Latitude = latitude;
}
public override bool Equals(object obj)
{
if (obj == null)//步骤1
return false;
if (this.GetType() != obj.GetType())//步骤3
return false;
return Equals((Coordinate)obj);//步骤4
//return base.Equals(obj);
}
public bool Equals(Coordinate obj)//步骤4 比较两个Coordinate对象时,可以避开Equals(Object obj)和GetType()检查
{
if (obj == null)//步骤1
return false;
if (ReferenceEquals(this, obj))//步骤2
return true;
if (this.GetHashCode() != obj.GetHashCode())//步骤5 效率低没有缓存,可以注释
return false;
System.Diagnostics.Debug.Assert(base.GetType() != typeof(object));
//步骤6 基类没有重写可以注释
if (!base.Equals(obj))
return false;
return ((Longitude.Equals(obj.Longitude)) && (Latitude.Equals(obj.Latitude)));//步骤7
}
/// <summary>
/// //步骤9
/// </summary>
/// <param name="leftHandSide"></param>
/// <param name="rightHandSide"></param>
/// <returns></returns>
public static bool operator ==(Coordinate leftHandSide, Coordinate rightHandSide)
{
if (ReferenceEquals(leftHandSide, null))
return ReferenceEquals(rightHandSide, null);
return (leftHandSide.Equals(rightHandSide));
}
public static bool operator !=(Coordinate leftHandSide, Coordinate rightHandSide)
{
return !(leftHandSide == rightHandSide);
}
/// <summary>
/// //步骤8
/// </summary>
/// <returns></returns>
public override int GetHashCode()
{
int hashCode = Longitude.GetHashCode();
if (Longitude.GetHashCode() != Latitude.GetHashCode())
hashCode ^= Latitude.GetHashCode();
return hashCode;
//return base.GetHashCode();
}
}
相等性实现基本原则:
1.Equals()、==、!=运算符应该一起实现
2.一个类型在Equals()、==、!=实现中应该使用相同算法
3.Equals()、==、!=实现时,也应实现一个类型的GetHashCode()
4.Equals()、==、!=、GetHashCode()永远不能引发异常
5.实现Icomparable时、与相等性有关的方法也应该实现