C# 程序员参考
Equals() 和运算符 == 的重载准则(C# 编程指南)
C# 中有两种不同的相等:引用相等和值相等。值相等是大家普遍理解的意义上的相等:它意味着两个对象包含相同的值。例如,两个值为 2 的整数具有值相等性。引用相等意味着要比较的不是两个对象,而是两个对象引用,这两个对象引用引用的是同一个对象。这可以通过简单的赋值来实现,如下面的示例所示:
C# 复制代码
System.Object a = new System.Object();
System.Object b = a;
System.Object.ReferenceEquals(a, b); //returns true
在上面的代码中,只存在一个对象,但存在对该对象的多个引用:a 和 b。由于它们引用的是同一个对象,因此具有引用相等性。如果两个对象具有引用相等性,则它们也具有值相等性,但是值相等性不能保证引用相等性。
若要检查引用相等性,应使用 ReferenceEquals。若要检查值相等性,应使用 Equals 或 Equals。
重写 Equals
Equals 是一个虚方法,允许任何类重写其实现。表示某个值(本质上可以是任何值类型)或一组值(如复数类)的任何类都应该重写 Equals。如果类型要实现 IComparable,则它应该重写 Equals。
Equals 的新实现应该遵循 Equals 的所有保证:
x.Equals(x) 返回 true。
x.Equals(y) 与 y.Equals(x) 返回相同的值。
如果 (x.Equals(y) && y.Equals(z)) 返回 true,则 x.Equals(z) 返回 true。
只要不修改 x 和 y 所引用的对象,x.Equals(y) 的后续调用就返回相同的值。
x.Equals(null) 返回 false。
Equals 的新实现不应该引发异常。建议重写 Equals 的任何类同时也重写 System.Object.GetHashCode。除了实现 Equals(对象)外,还建议所有的类为自己的类型实现 Equals(类型)以增强性能。例如:
C# 复制代码
class TwoDPoint : System.Object
{
public readonly int x, y;
public TwoDPoint(int x, int y) //constructor
{
this.x = x;
this.y = y;
}
public override bool Equals(System.Object obj)
{
// If parameter is null return false.
if (obj == null)
{
return false;
}
// If parameter cannot be cast to Point return false.
TwoDPoint p = obj as TwoDPoint;
if ((System.Object)p == null)
{
return false;
}
// Return true if the fields match:
return (x == p.x) && (y == p.y);
}
public bool Equals(TwoDPoint p)
{
// If parameter is null return false:
if ((object)p == null)
{
return false;
}
// Return true if the fields match:
return (x == p.x) && (y == p.y);
}
public override int GetHashCode()
{
return x ^ y;
}
}
可调用基类的 Equals 的任何派生类在完成其比较之前都应该这样做。在下面的示例中,Equals 调用基类 Equals,后者将检查空参数并将参数的类型与派生类的类型做比较。这样就把检查派生类中声明的新数据字段的任务留给了派生类中的 Equals 实现:
C# 复制代码
class ThreeDPoint : TwoDPoint
{
public readonly int z;
public ThreeDPoint(int x, int y, int z)
: base(x, y)
{
this.z = z;
}
public override bool Equals(System.Object obj)
{
// If parameter cannot be cast to ThreeDPoint return false:
ThreeDPoint p = obj as ThreeDPoint;
if ((object)p == null)
{
return false;
}
// Return true if the fields match:
return base.Equals(obj) && z == p.z;
}
public bool Equals(ThreeDPoint p)
{
// Return true if the fields match:
return base.Equals((TwoDPoint)p) && z == p.z;
}
public override int GetHashCode()
{
return base.GetHashCode() ^ z;
}
}
2007年5月13日星期日
订阅:
博文评论 (Atom)
没有评论:
发表评论