为什么这个简单的结构体为相等的对象返回不同的哈希码?

问题描述 投票:0回答:1

简单示例:

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

c# .net .net-core
1个回答
0
投票

此时您可能已经超越了这一点:但是您希望它们相等还是不相等。在我看来, DateTime.UnspecifiedDateTime.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 是很常见的。

© www.soinside.com 2019 - 2024. All rights reserved.