Je n'ai aucune expérience avec C#, mais autant que je sache, ce ne peut pas être nulle à l'intérieur d'une fonction membre (au moins c'est vrai qu'en C++ et Java, les langues que je connais)
Commençons par noter que votre affirmation est fausse.
En C++, l'envoi d'une méthode sur un nul récepteur est un comportement indéfini et un comportement indéfini signifie que tout peut arriver. "Rien du tout" inclut le programme de passage NULL
comme this
et continue comme si de rien n'était faux. Bien sûr, il est un peu ridicule de vérifier si this
est null en C++ parce que le chèque ne peut être vrai que si vous ne connaissez pas déjà ce que votre programme est en train de faire, parce que son comportement est indéfini.
Si this
peut être nul en Java je n'ai aucune idée.
Maintenant pour répondre à votre question à propos de C#. Supposons que, ==
n'est pas surchargé. Nous reviendrons sur ce point plus tard.
Votre méthode est écrite en C#. Supposons qu'il est appelé à partir d'un programme C# avec une valeur null récepteur. Le compilateur C# évalue si le récepteur pourrait éventuellement être nulle; si elle pourrait éventuellement être nulle alors qu'elle s'assure qu'il génère du code qui n'a nulle vérifier avant d'appeler la méthode. Par conséquent, cette vérification est inutile dans ce scénario. C'est bien sûr la 99.9999% scénario le plus probable.
Supposons qu'il est appelé par l'intermédiaire de la Réflexion, comme dans mike z de la réponse. Dans ce cas, il n'est pas le langage C# qui effectue l'invocation; plutôt, quelqu'un est délibérément abuser de la réflexion.
Supposons qu'il est appelé à partir d'une autre langue. Nous avons une méthode virtuelle; si elle est invoquée à partir de cette autre langue avec virtual envoi une valeur null vérification doit être effectuée, car sinon comment pourrions-nous savoir ce qui est dans le sous virtuel? Dans ce scénario, il ne peut pas être null.
Mais supposons qu'il est appelé à partir d'une autre langue à l'aide de non-virtuel de l'expédition. Dans ce cas, l'autre langue n'a pas besoin de mettre en œuvre le C# fonction de vérification de la valeur null. Il pourrait simplement appeler et passer la valeur null.
Il y a donc plusieurs façons d' this
pourrait être null
en C#, mais ils sont tous très bien sortir de l'ordinaire. Il est donc très rare pour les gens à écrire du code comme votre professeur. C#, programmeurs idiomatique supposons qu' this
n'est null
et de ne jamais vérifier.
Maintenant que nous avons obtenu que sur le chemin, nous allons critiquer ce code un peu plus.
public override bool Equals(object o) {
if (o == null)
return (this == null);
else {
return ((o is Person) && (this.dni == (o as Person).dni));
}
}
Tout d'abord il y a un bug évident. Nous présumons qu' this
pourrait être null, ok, nous allons l'utiliser. Ce qui l'arrête this.dni
de jeter référence nulle exception??? Si vous allez à supposer qu' this
peut être null alors au moins le faire de manière cohérente! (À Coverity nous nous référons à ce genre de situation comme une "avant null défaut".)
Prochaine: nous sommes primordial Equals
et ensuite à l'aide d' ==
à l'intérieur, sans doute à la moyenne de référence de l'égalité. Cette voie est la folie! Maintenant, nous avons une situation où l' x.Equals(y)
peut-être vrai, mais x==y
peut être faux! C'est horrible. S'il vous plaît ne pas y aller. Si vous allez de remplacer Equals
puis de surcharge ==
dans le même temps, et de mettre en oeuvre IEquatable<T>
pendant que vous y êtes.
(Maintenant, il y a de bonnes chances que la folie réside dans les deux sens; si ==
est compatible avec Equals
de la valeur sémantique alors personx == persony
peut être différent de celui (object)personx == (object)persony
, ce qui semble étrange aussi. La vente à emporter ici est que l'égalité est assez foiré en C#.)
En outre: que faire si ==
est remplacé plus tard? Maintenant, Equals
est l'appel d'un substituée ==
de l'opérateur, lorsque l'auteur du code veut clairement faire une référence de comparaison. C'est une recette pour les bugs.
Mes recommandations sont (1) écrire une méthode statique qui fait la bonne chose, et (2) utiliser ReferenceEquals
chaque fois que l'on pourrait peut-être être toute confusion sur ce genre d'égalité est-à-dire:
private static bool Equals(Person x, Person y)
{
if (ReferenceEquals(x, y))
return true;
else if (ReferenceEquals(x, null))
return false;
else if (ReferenceEquals(y, null))
return false;
else
return x.dni == y.dni;
}
Que bien couvre tous les cas. Notez qu'il est clair pour le lecteur lorsque la référence à l'égalité sémantique sont destinés. Notez également que ce code fait qu'il est très facile de mettre des points d'arrêt sur chaque possibilité, à des fins de débogage. Et enfin, à noter que nous avons de prendre le moins cher possible au début; si les objets sont de référence égale alors nous n'avons pas à faire de potentiellement coûteux comparaison des champs!
Maintenant, les autres méthodes sont simples:
public static bool operator ==(Person x, Person y)
{
return Equals(x, y);
}
public static bool operator !=(Person x, Person y)
{
return !Equals(x, y);
}
public override bool Equals(object y)
{
return Equals(this, y as Person);
}
public bool Equals(Person y)
{
return Equals(this, y);
}
Remarquez comment beaucoup plus élégant et clair, mon chemin est que votre professeur façon. Et remarquez que ma façon de poignées null this
sans jamais en comparant this
de la valeur null directement.
Nouveau: tous ce qui montre que la position de compromis fut trouvé, dans lequel à la fois la valeur de référence et l'égalité sont possibles et il y a quatre (==
, !=
, object.Equals(object)
et IEquatable<T>.Equals(T)
) des moyens à mettre en œuvre l'égalité, est très compliqué et déroutant, même sans supposer que this
peut ou ne peut pas être null
.
Si ce sujet vous intéresse, je décris un peu plus difficile problème sur mon blog cette semaine: comment mettre en œuvre les comparaisons en général, y compris les inégalités.
http://ericlippert.com/2013/10/07/math-from-scratch-part-six-comparisons/
Les commentaires sont particulièrement intéressants comme une critique de la façon dont C# poignées de l'égalité.
Enfin: n'oubliez pas de remplacer GetHashCode
. Assurez-vous que vous le faites à droite.