有时我需要不带字段的值对象(消息头、模式等),例如:
abstract class RequestHeader
{
}
sealed class FirstRequestHeader : RequestHeader
{
}
我在以下方法中使用它们:
partial class Server
{
private readonly IReadOnlyDictionary<RequestHeader, Action<object>> requestMap;
public void ProcessRequest(RequestHeader header, object request)
{
requestMap[header](request);
}
}
在这种情况下,GetHashCode
和Equals
方法的默认实现完全符合我的需要,因为我可以使用单例。
但是由于FirstRequestHeader
是一个不可变的值对象,我希望它的行为像一个真正的值对象:
var a = new FirstRequestHeader();
var b = new FirstRequestHeader();
Console.WriteLine(a == b &&
a.Equals(b) &&
a.GetHashCode() == b.GetHashCode()); // False, but should be True
重写==
操作符和Equals
方法很容易。
但是在这种情况下重写GetHashCode
方法的正确或推荐的方法是什么?
我可以期待一些答案(都有一些缺点):
- 每种类型的硬码常量哈希码
- 每次执行生成一个并保存在静态字段
- 通过
GetType
方法使用类型的哈希码 - 避免空对象(添加字段)
但是没有通过搜索
来确认假设。你会怎么做?
如果没有与类相关的数据,则只创建一个实例。
sealed class FirstRequestHeader : RequestHeader
{
public static readonly FirstRequestHeader Value = new FirstRequestHeader();
private FirstRequestHeader()
{
}
}
每种类型的硬码常量哈希码
如果您希望两个"相同"的对象被视为相等(并且没有字段或您的实例是相同的),这绝对是要走的路。
添加一个新字段,我假设您不会以任何有意义的方式修改它,结果相同,只是使它过于复杂。其他两种方法也是如此。
请注意,您可以选择任何值-您不需要担心不同类型之间可能的哈希码冲突,因此保持简单。
如果您希望所有实例具有相同的哈希码而不使用常量,您还可以使用类型为
的哈希码: public class FirstRequestHeader
{
public override int GetHashCode()
{
return this.GetType().GetHashCode();
}
}