2010-11-05 6 views
9

Il suffit de lire l'article msdn sur le remplacement des opérateurs d'égalité hereCast pour objet avant contrôle nul dans Equals primordial

L'extrait suivant me embrouille ...

// If parameter cannot be cast to Point return false. 
TwoDPoint p = obj as TwoDPoint; 
if ((System.Object)p == null) // <-- wtf? 
{ 
    return false; 
} 

Pourquoi est-il un casting à Object ici pour effectuer la comparaison null?

+1

Qu'est-ce que TwoDPoint? Peut-être que c'est un type de valeur: -D – Grzenio

+0

non. Vérifiez le lien ... – jgauffin

+0

Ils ont une meilleure ligne directrice pour Visual Studio 2012. Ils n'ont pas mis le lien dans l'article de 2005, alors je l'ai mis ici: [Comment: définir l'égalité de valeur pour un type (Guide de programmation C#) ] (http://msdn.microsoft.com/en-us/library/dd183755 (v = vs.110) .aspx). – Brk

Répondre

9

Les opérateurs appliquent par l'analyse statique (et les surcharges), pas les méthodes virtuelles (remplacements). Avec le casting, il effectue une vérification d'égalité de référence. Sans la distribution, il peut exécuter l'opérateur TwoDPoint. Je suppose que c'est pour éviter les problèmes quand un opérateur est ajouté.

Personnellement, cependant, je ferais une vérification de référence explicitement avec ReferenceEquals.

+0

+1 ... ce style est évidemment horriblement confus (cette question a été soulevée de nombreuses fois). 'ReferenceEquals' existe, il devrait être utilisé. –

+0

L'article MSDN explique ensuite pourquoi ReferenceEquals doit être utilisé :) –

+0

Vous obtiendrez un stackoverflow, comme je l'ai fait, lorsque vous comparez votre objet à null 'a == null', il réexécutera votre overridden' == ' ou '! =' encore et encore, jusqu'à ce qu'il se bloque. – ppumkin

0

Pour le forcer à utiliser la méthode Equals d'objet plutôt que sa propre version surchargée ... juste une supposition ...

+0

Oui, mais pourquoi? – jgauffin

0

Ce n'est pas inutile. Sans cette distribution, l'opérateur == étant surchargé serait appelé récursivement ...

+0

Non. J'ai juste essayé le code sans la distribution. – jgauffin

+0

@jgauffin: J'avais supposé que le code surchargeait l'opérateur ==, mais il surchargeait Equals. Dans ce cas, je ne vois aucune raison de le faire, mis à part le fait d'éviter les erreurs si l'opérateur == est présenté plus tard comme le suggère M. Marc Gravell. –

+0

Le point de l'article est que vous ne pouvez pas substituer Equals AND overload == sans utiliser de conversion vers Object. Si vous le faites, vous obtenez une exception NullReferenceException lorsque vous essayez de le faire (myVariable == null). Mais je suis d'accord sur l'utilisation de ReferenceEquals. – tandrewnichols

0

ci-dessous est la ligne qui fait la distribution

TwoDPoint p = obj as TwoDPoint 

la différence avec la distribution « normale » est que l'utilisation « Comme » il ne soulève pas d'exception si l'objet n'est pas « coulable ». Dans ce cas, si "p" n'est pas TwoDPoint, le type ne déclenchera pas d'exception (cast non valide) mais retournera null.

if ((System.Object)p == null) // <-- wtf? 
{ 
    return false; 
} 

cette vérification de code si le casting est bien passé, sinon p devrait être nul pour la raison ci-dessus

+1

Il a demandé pourquoi la distribution '(System.Object)' est là, rien d'autre. – jgauffin

+0

vous avez raison j'ai juste mal compris la question :-) –

3

Non! si vous ne faites pas cela, le moteur d'exécution lancera un appel récursif à l'opérateur d'égalité dans lequel vous êtes juste, ce qui entraîne une récursion infinie et, par conséquent, un débordement de pile.

+1

Nope. Ça ne sera pas. Essayez le code .. – jgauffin

+0

Oui, sans la distribution, elle se recurera jusqu'à ce que 'StackOverflow' – ppumkin

0

Notez qu'il s'agit de la documentation VS 2005. Je suppose que les gens qui rédigent la documentation avaient la même question et ne pouvaient pas trouver une bonne réponse; l'exemple a été changé pour VS 2008. Voici le current version:

public bool Equals(TwoDPoint p) 
{ 
    // If parameter is null, return false. 
    if (Object.ReferenceEquals(p, null)) 
    { 
     return false; 
    } 

    // Optimization for a common success case. 
    if (Object.ReferenceEquals(this, p)) 
    { 
     return true; 
    } 

    // If run-time types are not exactly the same, return false. 
    if (this.GetType() != p.GetType()) 
     return false; 

    // Return true if the fields match. 
    // Note that the base class is not invoked because it is 
    // System.Object, which defines Equals as reference equality. 
    return (X == p.X) && (Y == p.Y); 
} 
Questions connexes