【发布时间】:2010-03-24 17:31:14
【问题描述】:
有没有人有一个模板来编写一个像样的 equals 方法 - 我记得在 Effective Java 中,在处理子类时处理 equals 有问题。
我没有这本书,我不记得它是否是实用的建议 - 那么你如何编写一个可靠、健壮的 equals 方法实现?
【问题讨论】:
标签: c#
有没有人有一个模板来编写一个像样的 equals 方法 - 我记得在 Effective Java 中,在处理子类时处理 equals 有问题。
我没有这本书,我不记得它是否是实用的建议 - 那么你如何编写一个可靠、健壮的 equals 方法实现?
【问题讨论】:
标签: c#
可能是一个现成的建议,但:首先考虑不要覆盖Equals。正如您所提到的,基本上平等的性质不适用于子类化。然而,.NET API 中使用相等的几乎所有地方(例如字典、哈希集)都允许传入 IEqualityComparer<T>。使不同的对象负责相等使生活更加灵活:您可以使用不同的对象来确定哪个使用标准。
实现IEqualityComparer<T> 要简单得多——您仍然需要检查是否为空,但您不必担心类型是否合适,或者Equals 是否会被进一步覆盖。
另一种使正常的Equals 工作更顺利的方法是在大多数情况下完全避免继承——我不记得上次在我的代码中真正有意义地覆盖Equals 和 允许派生类。 sealed FTW :)
【讨论】:
您可能已经这样做了,但是您是否查看了有关实现 Equals() 的 MSDN 文章?
【讨论】:
一个好的equals方法的属性:
【讨论】:
如果您厌倦了为此编写大量样板文件,可以尝试使用为您实现它的基类。
public abstract class ValueObject<T> : IEquatable<T>
where T : ValueObject<T>
{
protected abstract IEnumerable<object> Reflect();
public override bool Equals(Object obj)
{
if (ReferenceEquals(null, obj)) return false;
if (obj.GetType() != GetType()) return false;
return Equals(obj as T);
}
public bool Equals(T other)
{
if (ReferenceEquals(null, other)) return false;
if (ReferenceEquals(this, other)) return true;
return Reflect().SequenceEqual(other.Reflect());
}
public override int GetHashCode()
{
return Reflect().Aggregate(36, (hashCode, value) => value == null ?
hashCode : hashCode ^ value.GetHashCode());
}
public override string ToString()
{
return "{ " + Reflect().Aggregate((l, r) => l + ", " + r) + " }";
}
}
现在要创建一个类似值的类,你只需说:
public class Person : ValueObject<Person>
{
public int Age { get; set; }
public string Name { get; set; }
protected override IEnumerable<object> Reflect()
{
return new object[] { Age, Name };
}
}
在 Reflect 覆盖中,您返回需要有助于相等的值序列。
不幸的是,这种方法无法帮助声明 operator ==,因为必须在派生类型上明确声明。
【讨论】:
【讨论】:
我通常会这样做:
public struct EmailAddress : IEquatable<EmailAddress>
{
public override bool Equals(object obj)
{
return obj != null && obj.GetType() == typeof(EmailAddress) && Equals((EmailAddress)obj);
}
public bool Equals(EmailAddress other)
{
return this.LocalPart == other.LocalPart && this.Domain == other.Domain;
}
}
【讨论】:
“好的”equals 方法是一种比较类的独特部分而忽略不利于独特性的部分的方法。因此,如果您有一个具有唯一 id 的类,您可以使用它来建立相等性,而忽略任何其他属性。不过,您通常还需要一些时间戳值。
【讨论】:
公共类人 { 公共字符串名称 { 获取;放; }
public int Age { get; set; }
public override bool Equals(object obj)
{
var objAsPerson = obj as Person;
if (obj == null)
{
return false;
}
if (this.Name != objAsPerson.Name)
{
return false;
}
if (this.Age != objAsPerson.Age)
{
return false;
}
return true;
}
}
【讨论】: