为何相等的简单结构体实例返回不同的哈希码?
值类型Equals与GetHashCode的优化差异疑问
示例代码
using System; using System.Globalization; var d1 = new DateTime(2023, 2, 28, 0, 0, 0, DateTimeKind.Unspecified); var d2 = new DateTime(2023, 2, 28, 0, 0, 0, DateTimeKind.Local); var foo1 = new Foo { d = d1 }; var foo2 = new Foo { d = d2 }; Console.WriteLine($"d1.Equals(d2): {d1.Equals(d2)}"); Console.WriteLine($"d1.GetHashCode() == d2.GetHashCode(): {d1.GetHashCode() == d2.GetHashCode()}"); Console.WriteLine($"foo1.Equals(foo2): {foo1.Equals(foo2)}"); Console.WriteLine($"foo1.GetHashCode() == foo2.GetHashCode(): {foo1.GetHashCode() == foo2.GetHashCode()}"); struct Foo { public DateTime d; }
运行输出
d1.Equals(d2): True d1.GetHashCode() == d2.GetHashCode(): True foo1.Equals(foo2): True foo1.GetHashCode() == foo2.GetHashCode(): False
问题背景
DateTime自身的Equals和GetHashCode方法都会忽略Kind属性,所以d1与d2的Equals返回True,哈希值也相等。但包含DateTime的自定义值类型Foo,它的Equals方法返回符合预期的True,可GetHashCode却返回了不同的值。
推测这和.NET对值类型的优化有关:当值类型的所有字段都是8字节宽度时,GetHashCode可能直接通过内存比较的方式计算哈希值,而非调用字段自身重写的GetHashCode方法。
疑问
- 这种基于内存比较的优化是否仅作用于GetHashCode,而不影响Equals方法?
- 该问题是仅在DateTime场景下出现,还是具有普遍性?比如优化逻辑没有检查字段是否重写了Equals/GetHashCode方法,导致所有满足字段宽度条件的值类型都会出现这种不一致?
内容的提问来源于stack exchange,提问作者synek317
相关产品推荐
相关产品推荐

