J'ai un collègue qui est fan de l'écriture de ses chèques nuls comme suit:
if (!ReferenceEquals(myObject, null))
Pour ma part, je trouve cette syntaxe difficile à lire et préfère:
if (myObject != null)
J'ai trouvé des articles et des questions sur le dépassement de pile traitant des avantages de ReferenceEquals en ce qui concerne la surcharge des opérateurs, mais en dehors du scénario de surcharge des opérateurs, y a-t-il un avantage à ReferenceEquals vs ==?
mais en dehors du scénario de surcharge de l'opérateur, y at-il un avantage à ReferenceEquals vs ==?
Non - le seul avantage (et je dirais que ce n'est pas vraiment un avantage) d'utiliser explicitement Object.ReferenceEquals
serait de ne jamais utiliser l'opérateur égal surchargé. Dans le cas non surchargé, l'opérateur == est défini comme "renvoie true si ses deux opérandes font référence au même objet" pour tous les "types de référence autres que chaîne". En tant que tel, son équivalent (à condition qu'il ne soit pas surchargé).
Personnellement, je suis également en faveur de l’utilisation de la deuxième syntaxe et la trouve plus facile à gérer pour la vérification nulle. Je soutiendrais également que tout operator==
surchargé devrait également fournir une vérification appropriée par rapport à null
, et dans le cas où cela ne serait pas le cas (ce qui serait étrange), il y aurait probablement une raison spécifique à cette décision qui vous vouloir utiliser la surcharge, pas ReferenceEquals
.
Avec c # 7, vous pouvez utiliser:
if ( !(myObject is null) )
C'est équivalent à
if (!ReferenceEquals(myObject, null))
Eh bien, si quelqu'un devait outrepasser les opérateurs == ou! =, Il pourrait lui faire faire ce qu'il voulait. Ils pourraient même avoir quelque chose de réel comme return true;
ou return false;
. De plus, s'il y a un opérateur surchargé, il y a de bonnes chances qu'il ne fonctionne pas aussi bien que ReferenceEquals
(non garanti, et ce n'est probablement pas suffisant pour importer, mais quand même).
Cela dit, étant donné qu’une implémentation raisonnable d’un opérateur surchargé n’est pas du tout un problème. Personnellement, je n'utilise pas ReferenceEquals
sauf si j'ai une raison impérieuse de ne pas utiliser l'opérateur ==
pour ce type ou dans ce cas particulier.
En termes de contrôles nuls, les deux doivent toujours renvoyer les mêmes résultats. Si une référence non nulle est jamais égale à zéro (même si vous utilisez le modèle Null Object), que ReferenceEquals ou l'opérateur == ait été utilisé, il s'agit d'un très mauvais. Donc, dans ce scénario, j'utiliserais == /! =.
Je dirais que, si l'opérateur == était surchargé, utilisez ReferenceEquals pourrait être légèrement plus rapide. La première chose que doit faire un == surchargé est de voir si les deux variables pointent sur le même objet. Ainsi, dans le cas d’un opérateur surchargé, vous vous retrouvez avec une trame supplémentaire sur la pile d’appels. L'utilisation de ReferenceEquals garantit également que c'est la vérification seulement effectuée.
Je voudrais aussi généralement utiliser == /! = Dans à peu près n'importe quel autre scénario. L'idée est que l'opérateur définit "l'égalité"; ce n'est pas toujours référentiel (en fait, la plupart des objets composés doivent être comparés structurellement pour l'égalité; ils sont égaux si leurs membres sont égaux). Théoriquement, l’objet sait comment se comparer au mieux à un autre objet, en termes d’égalité, d’ordre relatif, etc. Ainsi, plutôt que de coder en dur un élément de logique très spécifique et éventuellement incorrect, vous devez utiliser la nature orientée objet du langage pour: laissez l'objet vous dire s'il est égal à autre chose ou non.
ReferenceEquals peut être légèrement plus rapide. Comme mentionné précédemment, il est assuré qu'aucun opérateur Equals surchargé n'est appelé. De plus, ReferenceEquals garantit qu’une seule comparaison est effectuée au lieu de 2 en fonction de la mise en œuvre de l’opérateur Equals surchargé. Bien qu'il soit très probable que l'opérateur surchargé utilise ReferenceEquals lui-même comme première instruction.
Personnellement, j'utilise ReferenceEquals, mais uniquement sur les lieux où je suis en train de peaufiner les derniers cycles d'horloge (des endroits appelés éventuellement des millions de fois par seconde). Ou quand je n'ai aucun contrôle sur le type, comme dans le cas des génériques. ... Mais encore une fois seulement lorsque la performance est vraiment critique.
La balise VB.NET n'aurait probablement pas dû être incluse dans cette question car elle n'est pas autrement mentionnée, mais pour être complet, Is
est équivalent à Object.ReferenceEquals
et peut donc toujours être utilisé à la place de cet appel.
Donc, je voulais participer à cette conversation même si elle a un million d'années.
Disons que nous voulons écrire une méthode d'extension qui vérifie la valeur null. Nous pourrions faire ce qui suit:
public static bool IsNull<T>(this T value) where T : class, new()
{
return value == null;
}
mais ce code est ennuyeux.
La raison en est que T doit être une classe. Pourquoi? Parce que nous ne pouvons pas comparer les types de valeur avec null. Ce qui rend l’écriture de code générique décent une grosse douleur.
Sinon, vous pouvez associer la même méthode à object sans vous préoccuper de la nature de cet objet.
public static bool IsNull(this object value)
{
return object.ReferenceEquals(value, null);
}
Cela ouvre d'autres possibilités, comme écrire des monades à tolérance de pannes pour Linq par exemple, ou ce que vous voudrez, sans pour autant contraindre votre code générique.