我有一个 GetHashCode 的实现,我认为它相当健壮,但老实说,我是从互联网的深处挖掘出来的,虽然我理解所写的内容,但我觉得没有资格将其描述为“好” ' 或 GetHashCode 的“错误”实现。
我在 StackOverflow 上做了很多关于 GetHashCode 的阅读。是否有一个示例为什么 Equals/GetHashCode 应该在 NHibernate 中被覆盖?我认为这个线程可能是最好的信息来源,但它仍然让我感到疑惑。
考虑以下实体及其给定的 Equals 和 GetHashCode 实现:
public class Playlist : IAbstractDomainEntity
{
public Guid Id { get; set; }
public string Title { get; set;
public Stream Stream { get; set; }
// Use interfaces so NHibernate can inject with its own collection implementation.
public IList<PlaylistItem> Items { get; set; }
public PlaylistItem FirstItem { get; set; }
public Playlist NextPlaylist { get; set; }
public Playlist PreviousPlaylist { get; set; }
private int? _oldHashCode;
public override int GetHashCode()
{
// Once we have a hash code we'll never change it
if (_oldHashCode.HasValue)
return _oldHashCode.Value;
bool thisIsTransient = Equals(Id, Guid.Empty);
// When this instance is transient, we use the base GetHashCode()
// and remember it, so an instance can NEVER change its hash code.
if (thisIsTransient)
{
_oldHashCode = base.GetHashCode();
return _oldHashCode.Value;
}
return Id.GetHashCode();
}
public override bool Equals(object obj)
{
Playlist other = obj as Playlist;
if (other == null)
return false;
// handle the case of comparing two NEW objects
bool otherIsTransient = Equals(other.Id, Guid.Empty);
bool thisIsTransient = Equals(Id, Guid.Empty);
if (otherIsTransient && thisIsTransient)
return ReferenceEquals(other, this);
return other.Id.Equals(Id);
}
}
在这个实现中吹捧的安全检查数量似乎超过了顶部。它激发了我的信心——假设写这篇文章的人比我理解更多的极端案例——但也让我想知道为什么我看到这么多简单的实现。
为什么在重写 Equals 方法时重写 GetHashCode 很重要?查看所有这些不同的实现。下面是一个简单但评价很高的实现:
public override int GetHashCode()
{
return string.Format("{0}_{1}_{2}", prop1, prop2, prop3).GetHashCode();
}
这个实现会比我提供的更好还是更差?为什么?
两者都同样有效吗?实施 GetHashCode 时是否应遵循标准“指南”?上面的实现有什么明显的缺陷吗?如何创建测试用例来验证 GetHashCode 的实现?