【发布时间】:2013-07-07 15:28:16
【问题描述】:
出于单元测试的目的,我经常不得不重写 Equals 和 GetHashCode 方法。在此之后,我的课程开始看起来像这样:
public class TestItem
{
public bool BoolValue { get; set; }
public DateTime DateTimeValue { get; set; }
public double DoubleValue { get; set; }
public long LongValue { get; set; }
public string StringValue { get; set; }
public SomeEnumType EnumValue { get; set; }
public decimal? NullableDecimal { get; set; }
public override bool Equals(object obj)
{
var other = obj as TestItem;
if (other == null)
{
return false;
}
if (object.ReferenceEquals(this, other))
{
return true;
}
return this.BoolValue == other.BoolValue
&& this.DateTimeValue == other.DateTimeValue
&& this.DoubleValue == other.DoubleValue // that's not a good way, but it's ok for demo
&& this.EnumValue == other.EnumValue
&& this.LongValue == other.LongValue
&& this.StringValue == other.StringValue
&& this.EnumValue == other.EnumValue
&& this.NullableDecimal == other.NullableDecimal;
}
public override int GetHashCode()
{
return this.BoolValue.GetHashCode()
^ this.DateTimeValue.GetHashCode()
^ this.DoubleValue.GetHashCode()
^ this.EnumValue.GetHashCode()
^ this.LongValue.GetHashCode()
^ this.NullableDecimal.GetHashCode()
^ (this.StringValue != null ? this.StringValue.GetHashCode() : 0);
}
}
虽然做起来并不难,但在Equals 和GetHashCode 中维护相同字段的列表时会变得无聊且容易出错。有没有办法只列出一次用于相等检查和哈希码功能的文件? Equals 和 GetHashCode 应该按照这个设置列表来实现。
在我的想象中,此类设置列表的配置和使用可能看起来像
public class TestItem
{
// same properties as before
private static readonly EqualityFieldsSetup Setup = new EqualityFieldsSetup<TestItem>()
.Add(o => o.BoolValue)
.Add(o => o.DateTimeValue)
// ... and so on
// or even .Add(o => o.SomeFunction())
public override bool Equals(object obj)
{
return Setup.Equals(this, obj);
}
public override int GetHashCode()
{
return Setup.GetHashCode(this);
}
}
有一种方法可以在 java 中自动实现 hashCode 和 equals,例如 project lombok。我想知道是否有任何东西可以减少 C# 的样板代码。
【问题讨论】:
-
使用对象状态的正确表示覆盖 tostring,其哈希码将基于该输入。
-
@terrybozzio
ToString()比较?永远不要那样做。首先,它很昂贵。比较函数应该很快。其次,它甚至没有削减样板,它只是将它移动到其他地方。 -
@Mike:我对此表示怀疑。您上面的 GetHashCode 实现非常具体。我可能对那个实现根本不满意。与 Equals 相同(在较小程度上)。
-
使用正确的 tostring 覆盖是 testitem 类等于覆盖将减少以返回 obj.ToString() == this.ToString()。由于一切都支持 ToString 我们甚至不必检查正确的类型
-
@terrybozzio,但您仍然必须实现同样繁琐的
.ToString()方法。
标签: c# equals gethashcode