NaN 的 Equals 方法行为变更

已更新以下类型的 Equals(T other) 实例方法,以满足 IEquatable<T> 实现要求。 因此,该方法现在正确处理 NaN。 此更改可确保这些类型可以与 GetHashCodeDictionary<TKey,TValue> 以及其他哈希集一起正确使用。

旧行为

以前,Equals(T other) 实例方法遵循 IEEE 754 要求,并遵循 == 实现。 这意味着 NaN != NaN,即使两个 NaN 按位相同。

例如:

float f = float.NaN;
Console.WriteLine(f == f);         // False
Console.WriteLine(f.Equals(f));   // True

对于列出的几种类型:

Vector2 v = new Vector2(float.NaN);
Console.WriteLine(v == v);        // False
Console.WriteLine(v.Equals(v));   // False

这是有问题的,因为在字典中使用这些类型之一作为键意味着键永远无法被解析:

Vector2 v = new Vector2(float.NaN);
var s = new HashSet<Vector2>();
s.Add(v);
Console.WriteLine(s.Contains(v)); // False

新行为

现在的行为与基元浮点类型的行为相同,也就是说,==!= 方法继续遵循 IEEE 754 要求,其中 NaN != NaN。 但 Equals(T other) 实例方法遵循 IEquatable<T> 要求,以便实现 NaN.Equals(NaN)

例如(无更改):

float f = float.NaN;
Console.WriteLine(f == f);         // False
Console.WriteLine(f.Equals(f));   // True

对于列出的几种类型(第二行现在输出 True):

Vector2 v = new Vector2(float.NaN);
Console.WriteLine(v == v);        // False
Console.WriteLine(v.Equals(v));   // True

当在某些哈希集中使用时(输出现在显示 True):

Vector2 v = new Vector2(float.NaN);
var s = new HashSet<Vector2>();
s.Add(v);
Console.WriteLine(s.Contains(v)); // True

引入的版本

.NET 7

中断性变更的类型

此项更改可能会影响二进制兼容性

更改原因

前面的实现不符合 IEquatable<T>object.Equals(object obj) 的实现要求。 这导致受影响的类型在哈希集或 GetHashCode 中不可用。

如果更喜欢以前的行为,请切换到使用 ==!= 而不是 Equals(T other)

受影响的 API