简单示例:
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
(游乐场,net7)
DateTime
故意忽略其 Kind
和 Equals
方法中的 GetHashCode
。然而,在包含 GetHashCode
的简单结构的 DateTime
方法中,它似乎并没有被忽略。
我的猜测是,这可能与当所有字段都是 8 字节宽时使用
memcmp
的优化有关(例如 here 进行讨论)。
但是,有没有可能只用于
GetHashCode
而不用于Equals
?这是否“仅”是 DateTime
的问题,还是更普遍的问题,例如此优化不会检查覆盖 Equals
/GetHashCode
?
此时您可能已经超越了这一点:但是您希望它们相等还是不相等。在我看来, DateTime.Unspecified 和 DateTime.Local 不是相等的对象,因此 HashCode 方法正确返回。我相信,在进行比较的时区情况下,实际上它们可能会显示出不同的时间。甚至不同的日期,跨越国际日期变更线。也许这些对您的项目都不重要。
我很快就完成了这个工作,因为我想看看你的例子的实际效果:
struct Foo
{
public DateTime d;
public override bool Equals([NotNullWhen(true)] object? obj)
{
return base.GetHashCode().Equals(obj);
}
public override int GetHashCode()
{
return base.GetHashCode();
}
}
d1.Equals(d2): True
d1.GetHashCode() == d2.GetHashCode(): True
foo1.Equals(foo2): False
foo1.GetHashCode() == foo2.GetHashCode(): False
显然,这是一个示例,可能对您不起作用,但正如其他人所说,这可能是一个错误 - 在进行这样的比较时,重写自定义对象上的 Equals 和 GetHashCode 是很常见的。