suma sobrecarga operadores operador metodos fracciones constructores c# .net operator-overloading

c# - operadores - ¿Cómo verifico nulos en una sobrecarga de operador ''=='' sin recursión infinita?



sobrecarga de operadores c# (10)

Lo siguiente causará recursión infinita en el método de sobrecarga del operador ==

Foo foo1 = null; Foo foo2 = new Foo(); Assert.IsFalse(foo1 == foo2); public static bool operator ==(Foo foo1, Foo foo2) { if (foo1 == null) return foo2 == null; return foo1.Equals(foo2); }

¿Cómo verifico los nulos?


Un error común en las sobrecargas del operador == es usar (a == b) , (a ==null) o (b == null) para verificar la igualdad de referencia. Esto en cambio da como resultado una llamada al operador sobrecargado ==, causando un infinite loop . Use ReferenceEquals o coloque el tipo en Object para evitar el ciclo.

mira esto

// If both are null, or both are same instance, return true. if (System.Object.ReferenceEquals(a, b))// using ReferenceEquals { return true; } // If one is null, but not both, return false. if (((object)a == null) || ((object)b == null))// using casting the type to Object { return false; }

Pautas de referencia para Sobrecarga Equals () y Operador ==


Enviar a objeto en el método de sobrecarga:

public static bool operator ==(Foo foo1, Foo foo2) { if ((object) foo1 == null) return (object) foo2 == null; return foo1.Equals(foo2); }


Mi enfoque es hacer

(object)item == null

sobre lo cual confío en el operador de igualdad del objeto que no puede salir mal. O un método de extensión personalizado (y una sobrecarga):

public static bool IsNull<T>(this T obj) where T : class { return (object)obj == null; } public static bool IsNull<T>(this T? obj) where T : struct { return !obj.HasValue; }

o para manejar más casos, puede ser:

public static bool IsNull<T>(this T obj) where T : class { return (object)obj == null || obj == DBNull.Value; }

La restricción impide IsNull en los tipos de valores. Ahora es tan dulce como llamar

object obj = new object(); Guid? guid = null; bool b = obj.IsNull(); // false b = guid.IsNull(); // true 2.IsNull(); // error

lo que significa que tengo un estilo constante / no propenso a error de comprobación de nulos en todo. También he encontrado que el (object)item == null es muy muy ligeramente más rápido que Object.ReferenceEquals(item, null) , pero solo si importa (¡Actualmente estoy trabajando en algo donde tengo que optimizar todo! )

Para ver una guía completa sobre la implementación de verificaciones de igualdad, consulte ¿Qué es "Mejores prácticas" para comparar dos instancias de un Tipo de referencia?


Pruebe Object.ReferenceEquals(foo1, null)

De todos modos, no recomendaría sobrecargar el operador == ; debe usarse para comparar referencias y usar Equals para las comparaciones "semánticas".


Puede intentar usar una propiedad de objeto y capturar la NullReferenceException resultante. Si la propiedad que intentas es heredada o anulada de Object, entonces esto funciona para cualquier clase.

public static bool operator ==(Foo foo1, Foo foo2) { // check if the left parameter is null bool LeftNull = false; try { Type temp = a_left.GetType(); } catch { LeftNull = true; } // check if the right parameter is null bool RightNull = false; try { Type temp = a_right.GetType(); } catch { RightNull = true; } // null checking results if (LeftNull && RightNull) return true; else if (LeftNull || RightNull) return false; else return foo1.field1 == foo2.field2; }


Si está utilizando C # 7 o posterior, puede usar la coincidencia nula de patrones constantes:

public static bool operator==(Foo foo1, Foo foo2) { if (foo1 is null) return foo2 is null; return foo1.Equals(foo2); }

Esto le da un código ligeramente más ordenado que el objeto que llama. ReferenceEquals (foo1, null)


Si he reemplazado bool Equals(object obj) y quiero que el operador == y Foo.Equals(object obj) devuelvan la misma respuesta, generalmente implemento el operador != esta manera:

public static bool operator ==(Foo foo1, Foo foo2) { return object.Equals(foo1, foo2); } public static bool operator !=(Foo foo1, Foo foo2) { return !object.Equals(foo1, foo2); }

El operador == luego de hacer todas las comprobaciones nulas para mí termina llamando a foo1.Equals(foo2) que he anulado para hacer la comprobación real si las dos son iguales.


Use ReferenceEquals . Desde los foros de MSDN :

public static bool operator ==(Foo foo1, Foo foo2) { if (ReferenceEquals(foo1, null)) return ReferenceEquals(foo2, null); if (ReferenceEquals(foo2, null)) return false; return foo1.field1 == foo2.field2; }


Use ReferenceEquals :

Foo foo1 = null; Foo foo2 = new Foo(); Assert.IsFalse(foo1 == foo2); public static bool operator ==(Foo foo1, Foo foo2) { if (object.ReferenceEquals(null, foo1)) return object.ReferenceEquals(null, foo2); return foo1.Equals(foo2); }


El método estático Equals(Object, Object) indica si dos objetos, objA y objB , son iguales. También le permite probar objetos cuyo valor sea null para la igualdad. Compara objA y objB para la igualdad de la siguiente manera:

  • Determina si los dos objetos representan la misma referencia de objeto. Si lo hacen, el método devuelve true . Esta prueba es equivalente a llamar al método ReferenceEquals . Además, si tanto objA como objB son null , el método devuelve true .
  • Determina si objA u objB es null . Si es así, devuelve false . Si los dos objetos no representan la misma referencia de objeto y ninguno es null , llama a objA.Equals(objB) y devuelve el resultado. Esto significa que si objA anula el Object.Equals(Object) , se llama a esta anulación.

.

public static bool operator ==(Foo objA, Foo objB) { return Object.Equals(objA, objB); }