2010-06-09 3 views
16

lorsque j'essaie de surcharger l'opérateur == et! = En C#, et remplacer Equal comme recommandé, j'ai trouvé Je n'ai aucun moyen de distinguer un objet normal et null. Par exemple, j'ai défini un complexe de classe.surcharge == (et! =, Bien sûr) opérateur, puis-je contourner == pour déterminer si l'objet est nul

public static bool operator ==(Complex lhs, Complex rhs) 
{ 
    return lhs.Equals(rhs); 
} 

public static bool operator !=(Complex lhs, Complex rhs) 
{ 
    return !lhs.Equals(rhs); 
} 

public override bool Equals(object obj) 
{ 
    if (obj is Complex) 
    { 
     return (((Complex)obj).Real == this.Real && 
        ((Complex)obj).Imaginary == this.Imaginary); 
    } 
    else 
    { 
     return false; 
    } 
} 

Mais quand je veux utiliser

if (temp == null) 

quand la température est vraiment nulle, une exception se produit. Et je ne peux pas utiliser == pour déterminer si le lhs est nul, ce qui provoquera une boucle infinie.

Que dois-je faire dans cette situation?

Une façon dont je peux penser est à nous quelque chose comme Class.Equal (objet, objet) (si elle existe) pour contourner le == lorsque je fais la vérification.

Quelle est la manière normale de résoudre le problème?

Merci.

+0

duplication possible de [Comment vérifier les valeurs null dans une surcharge '==' sans récursion infinie?] (Http://stackoverflow.com/questions/73713/how-do-i-check-for-nulls -in-an-operator-overload-without-infinite-récursion) – Sam

Répondre

10

Vous devriez envisager d'utiliser la méthode statique Equals dans les opérateurs de surcharge (qui appellera l'instance méthode Equals):

public static bool operator ==(Complex lhs, Complex rhs) 
{ 
    return Equals(lhs, rhs); 
} 

public static bool operator !=(Complex lhs, Complex rhs) 
{ 
    return !Equals(lhs, rhs); 
} 

Remarque: Vous pouvez également vérifier null dans la méthode Equals.

Vous pouvez également lire le Object.Equals Topic on MSDN, qui est une excellente source d'échantillons.

+0

Merci, cela fonctionne, mais je ne sais pas pourquoi. Et, pourquoi Object peut-il être omis dans Object.Equals()? Et je n'ai pas trouvé pourquoi cela peut empêcher le problème nul dans MSDN. (Vérifie-t-il null en premier?) – LLS

+1

Vous n'avez pas besoin du préfixe de la classe Object car Complex hérite de Object; Complex voir les méthodes statiques de l'objet. Je ne connais pas les internes de la méthode statique Equals, mais il vérifie probablement null avant d'appeler la méthode Equals de l'instance. –

+1

Si lhs n'est pas nul, le static Equals appelle la méthode d'instance Equals on lhs. Si lhs est nul, Equals compare les références de lhs et rhs. –

14

Vous pouvez utiliser ce qui suit en haut de votre Equals Prioritaire:

if (Object.ReferenceEquals(obj, null)) 
    return false; 

L'exception que vous obtenez est probablement un StackOverflowException parce que votre opérateur == provoquera une récursion infinie.

EDIT:

Si complexe est un struct vous ne devriez pas avoir de problèmes avec NullReferenceExceptions. ! Si complexe est une classe, vous pouvez modifier l'implémentation du == et l'opérateur = Surcharges pour éviter l'exception (Laurent Etiemble a déjà souligné dans sa réponse):

public static bool operator ==(Complex lhs, Complex rhs) 
{ 
    return Equals(lhs, rhs); 
} 

public static bool operator !=(Complex lhs, Complex rhs) 
{ 
    return !Equals(lhs, rhs); 
} 
+0

En fait c'est la référence d'objet qui n'est pas définie sur une instance d'un objet. Ça devrait marcher, merci. :) – LLS

+0

L'exception existe toujours, car null.Equals() est tenté d'être appelé. – LLS

+0

Je considérerais faire une structure complexe au lieu d'une classe. –

0

Il y a une meilleure approche puis en utilisant les opérateurs is et cast:

Complex c = obj as Complex; 
return (c != null) && (c.Real == this.Real) && (c.Imaginary == this.Imaginary); 

Voici un test rapide inquiétant Equals remplacement de l'opérateur et la comparaison avec null:

class Complex 
{ 
    public override bool Equals(object obj) 
    { 
     if (obj is Complex) 
     { 
      return true; 
     } 
     else 
     { 
      return false; 
     } 
    } 
} 

Debugging n'étape pas en Corps de l'opérateur:

var b = (new Complex() == new Complex()); 
+0

Merci, mais il semble que c! = Null va provoquer une boucle infinie. – LLS

+0

@LLS: Vraiment? Intéressant. Pas sûr que la comparaison avec 'null' utilisera l'opérateur de comparaison' object'. Mais peut-être .. – abatishchev

+0

@LLS: Voir ma mise à jour – abatishchev

2
public static bool operator ==(Complex lhs, Complex rhs) 
{ 
    if (Object.ReferenceEquals(lhs, null)) 
    { 
     return Object.ReferenceEquals(rhs, null); 
    } 

    return lhs.Equals(rhs); 
} 

public static bool operator !=(Complex lhs, Complex rhs) 
{ 
    return !(lhs == rhs); 
} 

test de l'unité de l'homme pauvre

Action<Complex, Complex> tester = (left, right) => 
{ 
    Console.WriteLine(left == right); 
    Console.WriteLine(left != right); 
    Console.WriteLine(left == null); 
    Console.WriteLine(left != null); 
    Console.WriteLine("---"); 
}; 

tester(new Complex(), new Complex()); 
tester(null, new Complex()); 
tester(null, null); 
tester(new Complex(), null); 
+0

Merci beaucoup. C'est facile à comprendre. – LLS

0

Je pense que vous tester pour null qui devraient dans la mise en œuvre de l'opérateur ==. Sinon, quand lhs est nul, vous appelleriez Complex (null). Equals (je ne sais pas pour C#, mais en Java ce serait une exception Nullpointer)

Pour tester null, je suggère quelque chose comme:

if (null == lhs && null == rhs) return true 
else if (null == lhs) return false 
else return lhs.Equals(rhs); 

Ainsi, Object.Equals sera appelé pour toutes les comparaisons == ci-dessus.

+0

Vous obtenez un appel récursif à l'opérateur ==. –

+0

Ok, intéressant. Juste être curieux, comment se fait que l'opérateur == (Complex, Complex) est appelé, quand je teste null == lhs? Comment le compilateur décide-t-il que "null" est de type Complex? – nang