Cambio de comportamiento de los métodos Equals para NaN

El método de instancia Equals(T other) de los siguientes tipos se actualizó para cumplir los requisitos de la implementación de IEquatable<T>. Como resultado, el método ahora controla NaN correctamente. Este cambio garantiza que los tipos se pueden usar correctamente junto con GetHashCode, Dictionary<TKey,TValue> y otros conjuntos de hash.

Comportamiento anterior

Antes, el método de instancia Equals(T other) seguía los requisitos 754 de la IEEE y se posponía hasta la implementación ==. Esto llevaba a NaN != NaN, incluso cuando los dos NaN son idénticos bit a bit.

Por ejemplo:

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

Mientras que para varios de los tipos enumerados:

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

Esto es problemático porque el uso de uno de estos tipos como clave en un diccionario significaba que la clave nunca se podía resolver:

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

Comportamiento nuevo

El comportamiento es ahora el mismo que para los tipos primitivos de punto flotante: los métodos == y != siguen los requisitos 754 de la IEEE, en los que se produce NaN != NaN. Pero los métodos de instancia Equals(T other) siguen los requisitos de IEquatable<T> para que se produzca NaN.Equals(NaN).

Por ejemplo (sin cambios):

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

Mientras que para varios de los tipos enumerados (la segunda línea ahora imprime True):

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

Y cuando se usan en algún conjunto hash (la salida ahora imprime True):

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

Versión introducida

.NET 7

Tipo de cambio importante

Este cambio puede afectar a la compatibilidad binaria.

Motivo del cambio

La implementación anterior no cumplió los requisitos de implementación de IEquatable<T> o de object.Equals(object obj). Esto dio lugar a que los tipos afectados no se pudieran usar en conjuntos hash o con GetHashCode.

Si prefiere el comportamiento anterior, puede recuperarlo usando == o != en vez de Equals(T other).

API afectadas