对于引用平等,我使用object.ReferenceEquals
如您所说,尽管您也可以将引用转换为对象并进行比较(只要它们是引用类型)。
对于2和3,它真的取决于开发人员想要什么,如果他们想要将相等定义为身份或值相等。通常,我喜欢将Equals()保留为值相等,然后为外部比较器提供身份相等。
大多数比较项目的方法都让您能够传入自定义比较器,这就是我通常在任何自定义相等比较器(如身份)中传递的位置,但这就是我。
正如我所说,这是我的典型用法,我也构造的对象模型在那里我只考虑属性的子集来表示身份和其他人不比较。
您可以随时创建一个非常简单的ProjectionComparer,它可以接受任何类型的数据并根据投影创建一个比较器,使得在需要的地方传递自定义比较器以识别标识等非常容易,并且只需等待Equals()方法值。
而且,通常情况下,我个人不超载==除非我写的是需要典型的比较操作的值类型,因为运算符重载和超载怎么都没有覆盖这么大的混乱。
但同样,这只是我的:-)
UPDATE意见这里是我的投影比较器,你可以找到许多其他的实现,当然,不过这一次很适合我,它实现了两个EqualityComparer<TCompare>
(支持bool Equals(T, T)
和int GetHashCode(T)
和IComparer<T>
支持Compare(T, T)
):
public sealed class ProjectionComparer<TCompare, TProjected> : EqualityComparer<TCompare>, IComparer<TCompare>
{
private readonly Func<TCompare, TProjected> _projection;
// construct with the projection
public ProjectionComparer(Func<TCompare, TProjected> projection)
{
if (projection == null)
{
throw new ArgumentNullException("projection");
}
_projection = projection;
}
// Compares objects, if either object is null, use standard null rules
// for compare, then compare projection of each if both not null.
public int Compare(TCompare left, TCompare right)
{
// if both same object or both null, return zero automatically
if (ReferenceEquals(left, right))
{
return 0;
}
// can only happen if left null and right not null
if (left == null)
{
return -1;
}
// can only happen if right null and left non-null
if (right == null)
{
return 1;
}
// otherwise compare the projections
return Comparer<TProjected>.Default.Compare(_projection(left), _projection(right));
}
// Equals method that checks for null objects and then checks projection
public override bool Equals(TCompare left, TCompare right)
{
// why bother to extract if they refer to same object...
if (ReferenceEquals(left, right))
{
return true;
}
// if either is null, no sense checking either (both are null is handled by ReferenceEquals())
if (left == null || right == null)
{
return false;
}
return Equals(_projection(left), _projection(right));
}
// GetHashCode method that gets hash code of the projection result
public override int GetHashCode(TCompare obj)
{
// unlike Equals, GetHashCode() should never be called on a null object
if (obj == null)
{
throw new ArgumentNullException("obj");
}
var key = _projection(obj);
// I decided since obj is non-null, i'd return zero if key was null.
return key == null ? 0 : key.GetHashCode();
}
// Factory method to generate the comparer for the projection using type
public static ProjectionComparer<TCompare, TProjected> Create<TCompare,
TProjected>(Func<TCompare, TProjected> projection)
{
return new ProjectionComparer<TCompare, TProjected>(projection);
}
}
这使你可以做这样的事情:
List<Employee> emp = ...;
// sort by ID
emp.Sort(ProjectionComparer.Create((Employee e) => e.ID));
// sort by name
emp.Sort(ProjectionComparer.Create((Employee e) => e.Name));
到目前为止,我发现的一切似乎都指向WPF,使用'Equals()'而不是'ReferenceEquals()'或'=='来执行相等操作。 [链接1](http://www.lhotka.net/weblog/DataRefreshInWPF.aspx)[链接2](http://kentb.blogspot.com/2007/03/beware-datacontext-and-equals.html) 。可能是因为你的同事改变了类的'Equals()'方法以单向工作,改变了数据,期望数据绑定更新,并且它不是因为Equals()仍然返回true? –
谢谢,我认为第二个链接的开头段落完美地解释了它(并且比我的同事更好!)。 – SonOfPirate