Lo siguiente causará una recursividad 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 si hay nulos?
c#
.net
operator-overloading
Andrew Jones
fuente
fuente
Assert.IsFalse(foo2 == foo1);
foo1.Equals(foo2)
significa si, por ejemplo, quierofoo1 == foo2
sólo sifoo1.x == foo2.x && foo1.y == foo2.y
? ¿No es esto responder ignorando el caso dóndefoo1 != null
perofoo2 == null
?if (foo1 is null) return foo2 is null;
Transmitir a objeto en el método de sobrecarga:
fuente
(object)foo1 == null
ofoo1 == (object)null
irán a la sobrecarga incorporada==(object, object)
y no a la sobrecarga definida por el usuario==(Foo, Foo)
. Es como la resolución de sobrecargas en los métodos.Utilice
ReferenceEquals
. Desde los foros de MSDN :fuente
Tratar
Object.ReferenceEquals(foo1, null)
De todos modos, no recomendaría sobrecargar al
==
operador; debe usarse para comparar referencias y usarseEquals
para comparaciones "semánticas".fuente
Si he anulado
bool Equals(object obj)
y quiero que el operador==
yFoo.Equals(object obj)
devuelva el mismo valor, generalmente implemento el!=
operador de esta manera:==
Luego, el operador , después de hacer todas las comprobaciones nulas, terminará llamandofoo1.Equals(foo2)
que he anulado para hacer la verificación real si los dos son iguales.fuente
Object.Equals(Object, Object)
lado a ladoObject.ReferenceEquals(Object, Object)
, está bastante claro queObject.Equals(Object, Object)
hace todo como se sugiere en las otras respuestas listas para usar. ¿Por qué no usarlo?==
operador si todo lo que desea es un comportamiento predeterminado. Solo debe sobrecargar cuando necesite implementar una lógica de comparación personalizada, es decir, algo más que una verificación de igualdad de referencia.==
es deseable (la pregunta lo implica) simplemente estoy apoyando esta respuesta sugiriendo queObject.Equals(Object, Object)
hace que otros trucos como el usoReferenceEquals
o las conversiones explícitas sean innecesarios (por lo tanto, "¿por qué no usarlo?", "eso" serEquals(Object, Object)
). Incluso si no está relacionado, su punto también es correcto, y yo iría más allá: solo la sobrecarga==
para los objetos que podemos clasificar como "objetos de valor".Object.Equals(Object, Object)
a su vez llama a Object.Equals (Object), que es un método virtual que Foo probablemente anula. El hecho de que haya introducido una llamada virtual en su verificación de igualdad podría afectar la capacidad del compilador para optimizar (por ejemplo, en línea) estas llamadas. Esto probablemente sea insignificante para la mayoría de los propósitos, pero en ciertos casos, un pequeño costo en un operador de igualdad puede significar un costo enorme para los bucles o las estructuras de datos ordenadas.Si está utilizando C # 7 o posterior, puede utilizar la coincidencia de patrones constantes nulos:
Esto le da un código un poco más ordenado que el que llama al objeto. ReferenceEquals (foo1, null)
fuente
public static bool operator==( Foo foo1, Foo foo2 ) => foo1?.Equals( foo2 ) ?? foo2 is null;
En realidad, existe una forma más sencilla de verificar
null
en este caso:¡Eso es!
Esta característica se introdujo en C # 7
fuente
Mi enfoque es hacer
en el que confío en
object
el propio operador de igualdad que no puede fallar. O un método de extensión personalizado (y una sobrecarga):o para manejar más casos, puede ser:
La restricción impide los
IsNull
tipos de valor. Ahora es tan dulce como llamarlo que significa que tengo un estilo consistente / no propenso a errores de verificación de nulos en todo momento. También he descubierto que
(object)item == null
es muy, muy ligeramente más rápido queObject.ReferenceEquals(item, null)
, pero solo si importa (¡actualmente estoy trabajando en algo en lo que tengo que micro-optimizar todo!).Para ver una guía completa sobre la implementación de verificaciones de igualdad, consulte ¿Cuál es la "práctica recomendada" para comparar dos instancias de un tipo de referencia?
fuente
DbNull
, en mi opinión, los casos en los que esto no generaría problemas relacionados con SRP son bastante raros. Sin embargo, solo señalando el olor del código, podría ser muy apropiado.El
Equals(Object, Object)
método estático indica si dos objetos,objA
yobjB
, son iguales. También le permite probar objetos cuyo valor esnull
de igualdad. ComparaobjA
yobjB
por igualdad de la siguiente manera:true
. Esta prueba es equivalente a llamar alReferenceEquals
método. Además, si ambosobjA
yobjB
sonnull
, el método regresatrue
.objA
oobjB
esnull
. Si es así, vuelvefalse
. Si los dos objetos no representan la misma referencia de objeto y ninguno lo esnull
, llamaobjA.Equals(objB)
y devuelve el resultado. Esto significa que siobjA
anula elObject.Equals(Object)
método, se llama a esta anulación..
fuente
respondiendo más al operador anulante cómo comparar con nulo que redirige aquí como un duplicado.
En los casos en que esto se hace para admitir objetos de valor, encuentro que la nueva notación es útil y me gusta asegurarme de que solo haya un lugar donde se realice la comparación. Además, aprovechar Object.Equals (A, B) simplifica las comprobaciones nulas.
Esto sobrecargará ==,! =, Equals y GetHashCode
Para objetos más complicados, agregue comparaciones adicionales en Equals y un GetHashCode más rico.
fuente
Para una sintaxis moderna y condensada:
fuente
mira esto
Directrices de referencia para sobrecargar Equals () y Operador ==
fuente
Puede intentar usar una propiedad de objeto y capturar la NullReferenceException resultante. Si la propiedad que prueba se hereda o se anula de Object, esto funciona para cualquier clase.
fuente