2008-09-17 10 views
7

Duplicar posible:
How do I check for nulls in an '==' operator overload without infinite recursion?mejor manera de manejar nula cuando la escritura es igual operador

Cuando sobrecargar el operador == para los objetos que normalmente escribir algo como esto:

public static bool operator ==(MyObject uq1, MyObject uq2) { 
     if (((object)uq1 == null) || ((object)uq2 == null)) return false; 
     return uq1.Field1 == uq2.Field1 && uq1.Field2 == uq2.Field2; 
    } 

Si no realiza el down-cast para objetar, la función recurre en sí misma, pero me pregunto si no hay una mejor manera?

+1

Ver este enlace también para una implementación adecuada en general http://stackoverflow.com/questions/104158/what-is-best-practice-for-comparing-wo-instances-of-a-reference-type – nawfal

Respuesta

2

ReferenceEquals (objeto obj1, objeto obj2)

+0

Esto no parece de hecho abordan el problema: ReferenceEquals no le dirá si uno es nulo y el otro no, por ejemplo. –

+0

¿Por qué las personas votan esto? Por mi ejemplo, está claro que ReferenceEquals no es lo que estoy buscando –

+0

Heh, +4 votos y -4 votos :) – ripper234

-1
if ((object)uq1 == null) 
    return ((object)uq2 == null) 
else if ((object)uq2 == null) 
    return false; 
else 
    //return normal comparison 

Esto se compara como iguales cuando ambos son nulos.

+1

Esto hace lo mismo que hace mi ejemplo solo en términos más complicados –

-1

Siga el tratamiento DB:

null == <anything> is always false 
+0

Esto no resuelve el problema, x = = y si uno es nulo repetirá la función como he dicho –

2

@ neouser99: Esa es la solución correcta, sin embargo, la parte que se pierde es que cuando anulando el operador de igualdad (el operador ==) también se debe anular la función de los Iguales y simplemente haga que el operador llame a la función. No todos los lenguajes .NET soportan la sobrecarga del operador, de ahí el motivo para anular la función Equals.

+1

¿De verdad? Eso es interesante, he estado haciéndolo al revés –

+0

Si lo haces de esta manera, asegúrate de que el operador == comprueba nulo. null == null siempre. –

7

Como dice Microsoft,

Un error común en sobrecargas de operador == es el uso de (a == b), (a nulo == ), o (b == null) a verificar igualdad de referencia. Esto en su lugar da como resultado una llamada al operador sobrecargado ==, causando un bucle infinito. Utilice ReferenceEquals o aplique el tipo a Object, para evitar el bucle.

Así que use ReferenceEquals (a, null) || ReferenceEquals (b, null) es una posibilidad, pero la conversión a objeto es igual de buena (en realidad es equivalente, creo).

Así que sí, parece que debería haber una manera mejor, pero el método que utiliza es el recomendado.

Sin embargo, como se ha señalado, realmente DEBERÍA anular igual que cuando anula ==. Con los proveedores de LINQ escritos en diferentes idiomas y resolviendo la expresión en tiempo de ejecución, quién sabe cuándo se verá afectado por no hacerlo, incluso si usted es el propietario de todo el código.

+0

Sí, es un problema común pero la solución es anular la función Igual y hacer que la llamada de sobrecarga del operador sea igual a. ReferenceEquals resuelve un problema diferente y proporciona un tipo de igualdad completamente diferente. –

+2

Creo que malinterpretaste las llamadas de ReferenceEquals anteriores. Simplemente estoy probando la igualdad con NULL, con la comprensión de hacer un control de igualdad real además. NO está llamando a referenceequals para probar la igualdad de los argumentos. –

-1

¿Pero por qué no creas una función miembro de objeto? Ciertamente no se puede invocar en una referencia nula, por lo que está seguro de que el primer argumento no es nulo.

De hecho, pierde la simétrica de un operador binario, pero aún así ...

(nota sobre la respuesta Purfideas': Nula Nula podría ser igual si es necesario como un valor centinela de una matriz)

pensar también en la semántica de su función ==: a veces se realmente quiere ser capaz de elegir si se prueba para

  • identidad (puntos al mismo objeto)
  • Valor Igualdad
  • Equivalencia (por ejemplo 1,000001 es equivalente a 0,9999999)
+1

Lo siento, esto realmente no responde la pregunta. La pregunta es si hay una mejor manera de probar la igualdad que no sea la de downcasting –

0

Simplemente use Resharper para crearle Igual & métodos GetHashCode. Crea el código más completo para este propósito.

actualización que no le envió a propósito - Yo prefiero la gente a usar la función de ReSharper en lugar de copiar y pegar, ya que los cambios en el código de clase en clase. En cuanto al desarrollo de C# sin Resharper, no entiendo cómo vives, hombre.

De todos modos, aquí está el código para una clase simple (Generado por ReSharper 3.0, la versión más antigua - Tengo 4.0 en el trabajo, no me acuerdo actualmente si se crea un código idéntico)

public class Foo : IEquatable<Foo> 
{ 
    public static bool operator !=(Foo foo1, Foo foo2) 
    { 
     return !Equals(foo1, foo2); 
    } 

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

    public bool Equals(Foo foo) 
    { 
     if (foo == null) return false; 
     return y == foo.y && x == foo.x; 
    } 

    public override bool Equals(object obj) 
    { 
     if (ReferenceEquals(this, obj)) return true; 
     return Equals(obj as Foo); 
    } 

    public override int GetHashCode() 
    { 
     return y + 29*x; 
    } 

    private int y; 
    private int x; 
} 
+1

¿Y no querría publicarla para aquellos de nosotros que no tienen $ 400 para cancelar? –

+0

¿Por qué Bill Wagner no estaría de acuerdo con usted en este capítulo? http://my.safaribooksonline.com/book/programming/csharp/0321245660/csharp-language-elements/ch01lev1sec9 Él balbucea algo sobre Iguales siendo simétricos. –

+1

@Hamish - No lo sé, tendrás que ser más específico que eso. – ripper234

Cuestiones relacionadas