Question

Je dois faire une comparaison entre un objet et NULL. Lorsque l'objet n'est pas NULL, je le remplis avec des données.

Voici le code:

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

Cela fonctionne, mais lors de la boucle, l'objet région n'est PAS nul (je peux voir les données qu'il contient en mode débogage). Lors du débogage, pas à pas, il ne va pas à l'intérieur de l'instruction IF ... Lorsque je fais une recherche rapide avec l'expression suivante: Je vois que (région == null) renvoie false, et (région! = Null ) renvoie false également ... pourquoi et comment?

Mettre à jour

Quelqu'un a signalé que l'objet était == et! = surchargé:

    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);
    }
Était-ce utile?

La solution

L'opérateur == et / ou! = est-il surchargé pour la classe de l'objet region?

Maintenant que vous avez posté le code pour les surcharges:

Les surcharges devraient probablement ressembler à ce qui suit (code tiré des publications de Jon Skeet et 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);
}

Autres conseils

Les surcharges de l'opérateur sont rompues.

Premièrement, cela simplifie grandement la vie si! = est mis en œuvre en appelant simplement == et en inversant le résultat.

Deuxièmement, avant l'enregistrement de la nullité ==, il devrait y avoir:

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

Les deux surcharges sont incorrectes

 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 et r2 sont nuls, le premier test ( object.ReferenceEquals (r1, null) ) renverra false, même si r2 est également nul.

essayer

//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);
    }

Cela peut parfois arriver lorsque plusieurs threads travaillent avec les mêmes données. Si tel est le cas, vous pouvez utiliser un verrou pour les empêcher de s’embrouiller.

Pour la comparaison d'égalité d'un type & "; T &" ;, surchargez ces méthodes:

.
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)

Votre code de comparaison spécifique au type doit être placé au même endroit : la méthode d'interface sécurisée IEquatable<T> Equals(T other). Si vous comparez à un autre type (T2), implémentez également IEquatable<T2> et définissez le code de comparaison de champ pour ce type sur Egal (T2 autre).

Toutes les méthodes et tous les opérateurs surchargés doivent transmettre la tâche de comparaison d'égalité à la méthode d'instance Equals (T autre) principale, de type sécurisée pour le type, de sorte qu'une hiérarchie des dépendances propres soit maintenue et que des garanties plus strictes soient introduites à chaque niveau pour éliminer la redondance et la complexité non essentielle .

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
}

Discussion:

La mise en œuvre précédente centralise la comparaison (c'est-à-dire l'égalité de champs) spécifique au type à la fin de la mise en œuvre == pour le type. Les opérateurs != et !(obj1 == obj2) ont une implémentation parallèle mais opposée. Je préfère cela plutôt que d’avoir l’une référence l’autre, de sorte qu’il existe un appel supplémentaire à la méthode pour la personne dépendante. Si l'opérateur ReferenceEquals(obj1,obj2) appelle simplement l'opérateur Equals(object),Equals(T),==,!= plutôt que de proposer un opérateur tout aussi performant, vous pouvez également utiliser <=> et éviter l'appel de méthode supplémentaire. La comparaison à soi-même est laissée de côté par l'opérateur equals et les <=> implémentations, car elle peut entraîner 1. une surcharge inutile dans certains cas, et / ou 2. des performances incohérentes selon la fréquence à laquelle une instance est comparée à elle-même vs autres instances.

Une alternative que je n'aime pas, mais que je devrais mentionner, consiste à inverser cette configuration, en centralisant le code d'égalité spécifique au type dans l'opérateur d'égalité et en laissant les méthodes Equals dépendre de cela. On pourrait alors utiliser le raccourci <=> pour vérifier simultanément l’égalité de référence et l’égalité nulle, comme Philip l’a mentionné dans un précédent article, mais cette idée est trompeuse. On dirait que vous tuez deux oiseaux avec une pierre, mais que vous créez en fait plus de travail - après avoir déterminé que les objets ne sont ni à la fois nuls et identiques, vous devrez ensuite, ENCORE, vérifier si chaque instance est nul. Dans mon implémentation, vous vérifiez qu'une seule instance est nulle une seule fois. Au moment où la méthode d'instance Equals est appelée, il est déjà exclu que le premier objet comparé soit nul, il ne reste donc qu'à vérifier si l'autre est nul. Donc, après au plus deux comparaisons, nous passons directement à la vérification sur le terrain, quelle que soit la méthode utilisée (<=>). En outre, comme je l'ai mentionné, si vous comparez et vous objectez vraiment la plupart du temps, vous pouvez alors ajouter cette vérification dans la méthode Egalité juste avant de plonger dans les comparaisons sur le terrain. En ajoutant ce dernier point, vous pouvez toujours conserver la hiérarchie flux / dépendances sans introduire de contrôle redondant / inutile à tous les niveaux.

Alors, ces vérifications ne sont-elles pas correctes?

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

Il existe une autre possibilité que vous deviez cliquer sur l'icône d'actualisation en regard du paramètre que vous regardez. Les VS essaient de suivre la performance sans évaluer tous les énoncés / paramètres. Jetez un coup d'œil avant de commencer à modifier des lieux qui ne sont pas pertinents.

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

if (object.IsNullOrEmpty(r2))
{
    comp = false;
}
return comp;
Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top