Quick example:
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;
}
Prints:
d1.Equals(d2): True
d1.GetHashCode() == d2.GetHashCode(): True
foo1.Equals(foo2): True
foo1.GetHashCode() == foo2.GetHashCode(): False
DateTime
intentionally ignores Kind
in its Equals
and GetHashCode
methods. However, it seems that it is not ignored in the GetHashCode
methods of a simple struct which contains a DateTime
.
My guess is it might be related to this optimization which uses memcmp
when all fields are 8 bytes wide (discussed for example here).
However, is it possible that it is used only for GetHashCode
and not for Equals
? Is it "only" an issue with DateTime
or is it more general, e.g. this optimization doesn't check for overriden Equals
/GetHashCode
?