Pregunta

Necesito hacer una comparación entre un objeto y NULL.Cuando el objeto no es NULL lo lleno con algunos datos.

Aquí está el código:

 if (region != null)
 {
  ....
 }

Esto está funcionando, pero cuando se realiza un bucle y se repite en algún momento, el objeto de región NO es nulo (puedo ver los datos dentro de él en modo de depuración).En el paso a paso durante la depuración, no entra dentro de la declaración IF...Cuando hago una observación rápida con la siguiente expresión:Veo que (región == nulo) devuelve falso, Y (región! = nulo) también devuelve falso... ¿porque y como?

Actualizar

Alguien señala que el objeto estaba == y != sobrecargado:

    public static bool operator ==(Region r1, Region r2)
    {
        if (object.ReferenceEquals(r1, null))
        {
            return false;
        }
        if (object.ReferenceEquals(r2, null))
        {
            return false;
        }

        return (r1.Cmr.CompareTo(r2.Cmr) == 0 && r1.Id == r2.Id);
    }


    public static bool operator !=(Region r1, Region r2)
    {
        if (object.ReferenceEquals(r1, null))
        {
            return false;
        }
        if (object.ReferenceEquals(r2, null))
        {
            return false;
        }
        return (r1.Cmr.CompareTo(r2.Cmr) != 0 || r1.Id != r2.Id);
    }
¿Fue útil?

Solución

¿El operador == y / o! = está sobrecargado para la clase del objeto de región?

Ahora que ha publicado el código para las sobrecargas:

Las sobrecargas probablemente deberían tener el siguiente aspecto (código tomado de publicaciones hechas por Jon Skeet y Philip Rieck ):

public static bool operator ==(Region r1, Region r2)
{
    if (object.ReferenceEquals( r1, r2)) {
        // handles if both are null as well as object identity
        return true;
    }

    if ((object)r1 == null || (object)r2 == null)
    {
       return false;
    }        

    return (r1.Cmr.CompareTo(r2.Cmr) == 0 && r1.Id == r2.Id);
}

public static bool operator !=(Region r1, Region r2)
{
    return !(r1 == r2);
}

Otros consejos

Esas sobrecargas del operador están rotas.

En primer lugar, hace la vida mucho más fácil si! = se implementa simplemente llamando == e invirtiendo el resultado.

En segundo lugar, antes de que la nulidad se registre en == debería haber:

if (object.ReferenceEquals(r1, r2))
{
    return true;
}

Ambas sobrecargas son incorrectas

 public static bool operator ==(Region r1, Region r2)
    {
        if (object.ReferenceEquals(r1, null))
        {
            return false;
        }
        if (object.ReferenceEquals(r2, null))
        {
            return false;
        }

        return (r1.Cmr.CompareTo(r2.Cmr) == 0 && r1.Id == r2.Id);
    }

si r1 y r2 son nulos, la primera prueba ( object.ReferenceEquals (r1, null) ) devolverá falso, aunque r2 también sea nulo.

prueba

//ifs expanded a bit for readability
 public static bool operator ==(Region r1, Region r2)
    {
        if( (object)r1 == null && (object)r2 == null)
        {
           return true;
        }
        if( (object)r1 == null || (object)r2 == null)
        {
           return false;
        }        
        //btw - a quick shortcut here is also object.ReferenceEquals(r1, r2)

        return (r1.Cmr.CompareTo(r2.Cmr) == 0 && r1.Id == r2.Id);
    }

Esto a veces puede suceder cuando tienes varios subprocesos trabajando con los mismos datos. Si este es el caso, puede usar un candado para evitar que jueguen entre ellos.

Para comparar la igualdad de un tipo "T", sobrecargue estos métodos:

int GetHashCode() //Overrides Object.GetHashCode
bool Equals(object other) //Overrides Object.Equals; would correspond to IEquatable, if such an interface existed
bool Equals(T other) //Implements IEquatable<T>; do this for each T you want to compare to
static bool operator ==(T x, T y)
static bool operator !=(T x, T y)

Su código de comparación específico de tipo debe realizarse en un solo lugar:el tipo seguro IEquatable<T> método de interfaz Equals(T other).Si está comparando con otro tipo (T2), implemente IEquatable<T2> también y coloque el código de comparación de campo para ese tipo en Igual a (T2 otro).

Todos los métodos y operadores sobrecargados deben reenviar la tarea de comparación de igualdad al método de instancia principal Equals(T other) con seguridad de tipos, de modo que se mantenga una jerarquía de dependencia limpia y se introduzcan garantías más estrictas en cada nivel para eliminar la redundancia y la complejidad no esencial.

bool Equals(object other)
{
    if (other is T) //replicate this for each IEquatable<T2>, IEquatable<T3>, etc. you may implement
        return Equals( (T)other) ); //forward to IEquatable<T> implementation
    return false; //other is null or cannot be compared to this instance; therefore it is not equal
}

bool Equals(T other)
{
    if ((object)other == null) //cast to object for reference equality comparison, or use object.ReferenceEquals
        return false;
    //if ((object)other == this) //possible performance boost, ONLY if object instance is frequently compared to itself! otherwise it's just an extra useless check
        //return true;
    return field1.Equals( other.field1 ) &&
           field2.Equals( other.field2 ); //compare type fields to determine equality
}

public static bool operator ==( T x, T y )
{
    if ((object)x != null) //cast to object for reference equality comparison, or use object.ReferenceEquals
        return x.Equals( y ); //forward to type-safe Equals on non-null instance x
    if ((object)y != null)
        return false; //x was null, y is not null
    return true; //both null
}

public static bool operator !=( T x, T y )
{
    if ((object)x != null)
        return !x.Equals( y ); //forward to type-safe Equals on non-null instance x
    if ((object)y != null)
        return true; //x was null, y is not null
    return false; //both null
}

Discusión:

La implementación anterior centraliza el tipo específico (es decir,igualdad de campo) comparación con el final de la IEquatable<T> implementación para el tipo.El == y != Los operadores tienen una implementación paralela pero opuesta.Prefiero esto a tener una referencia a la otra, de modo que haya una llamada de método adicional para el dependiente.Si el != El operador simplemente llamará al == operador, en lugar de ofrecer un operador con el mismo rendimiento, entonces también puede utilizar !(obj1 == obj2) y evitar la llamada al método adicional.La comparación consigo mismo queda fuera del operador igual y el IEquatable<T> implementaciones, porque puede introducir 1.gastos generales innecesarios en algunos casos, y/o 2.Rendimiento inconsistente dependiendo de la frecuencia con la que se compara una instancia consigo misma frente a otras instancias.

Una alternativa que no me gusta, pero que debería mencionar, es revertir esta configuración, centralizando el código de igualdad específico del tipo en el operador de igualdad y hacer que los métodos Equals dependan de eso.Entonces se podría utilizar el atajo de ReferenceEquals(obj1,obj2) verificar la igualdad de referencia y la igualdad nula simultáneamente como Philip mencionó en una publicación anterior, pero esa idea es engañosa.Parece que estás matando dos pájaros de un tiro, pero en realidad estás creando más trabajo: después de determinar que los objetos no son nulos ni la misma instancia, TODAVÍA tendrás que verificar si cada instancia es nulo.En mi implementación, verifica que cualquier instancia sea nula exactamente una vez.Para cuando se llama al método de instancia Equals, ya se descarta que el primer objeto que se compara sea nulo, por lo que todo lo que queda por hacer es verificar si el otro es nulo.Entonces, después de dos comparaciones como máximo, saltamos directamente a la verificación de campo, sin importar qué método usemos (Equals(object),Equals(T),==,!=).Además, como mencioné, si realmente estás comparando y objetando a sí mismo la mayor parte del tiempo, entonces puedes agregar esa verificación en el método Iguales justo antes de sumergirte en las comparaciones de campo.El punto de agregarlo al final es que aún puede mantener la jerarquía de flujo/dependencia sin introducir una verificación redundante/inútil en cada nivel.

Entonces, estas comprobaciones aquí no son correctas:

public static bool operator !=(Region r1, Region r2)
{
    if (object.ReferenceEquals(r1, null))
    {
        return false;
    }
    if (object.ReferenceEquals(r2, null))
    {
        return false;
    }
...

Existe otra posibilidad de que necesite hacer clic en el icono de actualización junto al parámetro que está viendo. VS intenta mantenerse al día con el rendimiento sin evaluar cada declaración / parámetro. Eche un vistazo para asegurarse, antes de comenzar a hacer cambios en lugares que no son relevantes.

bool comp;
if (object.IsNullOrEmpty(r1))
{
    comp = false;
}

if (object.IsNullOrEmpty(r2))
{
    comp = false;
}
return comp;
Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top