Différence C # entre == et Equals ()

548

J'ai une condition dans une application Silverlight qui compare 2 chaînes, pour une raison quelconque, lorsque je l'utilise, ==elle renvoie false tandis que .Equals()renvoie true .

Voici le code:

if (((ListBoxItem)lstBaseMenu.SelectedItem).Content.Equals("Energy Attack"))
{
    // Execute code
}

if (((ListBoxItem)lstBaseMenu.SelectedItem).Content == "Energy Attack")
{
    // Execute code
}

Une raison pour laquelle cela se produit?

Drahcir
la source
8
Les chaînes remplacent ==, mais les opérateurs ne sont pas polymorphes. Dans ce code, l' ==opérateur est appelé sur type object, qui effectue une comparaison d'identité au lieu d'une valeur.
Drew Noakes
12
Pour développer le commentaire de @DrewNoakes: Le compilateur choisit une ==surcharge en fonction du type de compilation des opérandes. La Contentpropriété est object. Les opérateurs ne sont pas virtuels, donc l'implémentation par défaut de ==est appelée, donnant une comparaison d'égalité de référence. Avec Equals, l'appel passe à la méthode virtuelle object.Equals(object); stringremplace cette méthode et effectue une comparaison ordinale du contenu de la chaîne. Voir msdn.microsoft.com/en-us/library/fkfd9eh8(v=vs.110).aspx et referencesource.microsoft.com/#mscorlib/system/string.cs,507 .
phoog
6
L'explication de @ phoog est précise. Il convient de noter que lorsque le côté gauche de ==a le type au moment de la compilation objectet le côté droit a le type au stringmoment de la compilation, alors le compilateur C # doit choisir la surcharge (problématique, dans ce cas) operator ==(object, object); mais il sera un avertissement à la compilation qu'il pourrait être involontaire. Lisez donc les avertissements à la compilation! Pour résoudre le problème et continuer à l'utiliser ==, placez le côté gauche sur string. Si je me souviens bien, le texte d'avertissement le suggère.
Jeppe Stig Nielsen
1
@JeppeStigNielsen +1 pour les conseils de lecture des avertissements du compilateur. Encore mieux: activez l'option avertissements en tant qu'erreurs pour forcer tout le monde à y prêter attention.
phoog

Réponses:

429

Lorsque ==est utilisé sur une expression de type object, il sera résolu en System.Object.ReferenceEquals.

Equalsest juste une virtualméthode et se comporte comme telle, donc la version surchargée sera utilisée (qui, pour le stringtype, compare le contenu).

Mehrdad Afshari
la source
57
Sauf si l'opérateur est spécifiquement implémenté dans la classe
Dominic Cronin
23
@DominicCronin Ce n'est pas vrai. Même si == est implémenté dans la classe, il sera ignoré car le type à gauche de la comparaison est object. Il semble que les surcharges de l'opérateur soient déterminées au moment de la compilation et au moment de la compilation, tout ce qu'il sait, c'est que le côté gauche est un objet.
MikeKulls
4
@DominicCronin Je crois que votre première déclaration est correcte en ce sens que == se résoudra en objet mais votre deuxième déclaration que les surcharges d'opérateurs résolvent de manière similaire ne l'est pas. Ils sont assez différents, c'est pourquoi .Equals se résoudra en chaîne tandis que == se résoudra en objet.
MikeKulls
8
Pour être clair, le objecttype (notez la police monospace) est techniquement censé être "une expression de type System.Object". Cela n'a rien à voir avec le type d'exécution de l'instance à laquelle fait référence l'expression. Je pense que la déclaration «les opérateurs définis par l'utilisateur sont traités comme des virtualméthodes» est extrêmement trompeuse. Ils sont traités comme des méthodes surchargées et ne dépendent que du type de compilation des opérandes. En fait, une fois l'ensemble des opérateurs définis par l'utilisateur candidats calculés, le reste de la procédure de liaison sera exactement l'algorithme de résolution de surcharge de méthode
Mehrdad Afshari
4
@DominicCronin La partie trompeuse est que la virtualrésolution de la méthode dépend du type d'exécution réel d'une instance, alors que cela est complètement ignoré dans la résolution de surcharge de l'opérateur, et c'est en effet tout le point de ma réponse.
Mehrdad Afshari
314

Lors de la comparaison d'une référence d'objet à une chaîne (même si la référence d'objet fait référence à une chaîne), le comportement spécial de l' ==opérateur spécifique à la classe de chaîne est ignoré.

Normalement (lorsqu'il ne s'agit pas de chaînes, c'est-à-dire), Equalscompare les valeurs , tout en ==comparant les références d'objet . Si deux objets que vous comparez se réfèrent à la même instance exacte d'un objet, alors les deux renverront true, mais si l'un a le même contenu et provient d'une source différente (est une instance distincte avec les mêmes données), seul Equals sera retourner vrai. Cependant, comme indiqué dans les commentaires, la chaîne est un cas particulier car elle remplace l' ==opérateur de sorte que lorsqu'il s'agit uniquement de références de chaîne (et non de références d'objet), seules les valeurs sont comparées même s'il s'agit d'instances distinctes. Le code suivant illustre les différences subtiles de comportements:

string s1 = "test";
string s2 = "test";
string s3 = "test1".Substring(0, 4);
object s4 = s3;
Console.WriteLine("{0} {1} {2}", object.ReferenceEquals(s1, s2), s1 == s2, s1.Equals(s2));
Console.WriteLine("{0} {1} {2}", object.ReferenceEquals(s1, s3), s1 == s3, s1.Equals(s3));
Console.WriteLine("{0} {1} {2}", object.ReferenceEquals(s1, s4), s1 == s4, s1.Equals(s4));

La sortie est:

True True True
False True True
False False True
BlueMonkMN
la source
8
Repérez. L'opérateur '==' compare les références d'objet (comparaison superficielle) tandis que .Equals () compare le contenu de l'objet (comparaison approfondie). Comme l'a dit @mehrdad, .Equals () est remplacé pour fournir cette comparaison de contenu approfondie.
Andrew
1
Je vais laisser le post ici parce que je pense qu'il est utile de souligner ce qui ne se passe pas car il faut être très attentif pour le réaliser. (Et je pense que le code pour démontrer les compréhensions correctes et incorrectes vaut également la peine.) J'espère que la note ne descendra pas en dessous de 0.
BlueMonkMN
5
Surement, String implémente un opérateur == personnalisé. Si ce n'était pas le cas, l'utilisation de == ne comparerait pas le contenu. String est donc un mauvais exemple à utiliser ici, car il ne nous aide pas à comprendre le cas général où aucun opérateur personnalisé n'a été défini.
Dominic Cronin
6
+1 pour l'exemple de code épique, cela m'a fait comprendre cela. Affiche le cas général du type statique (type côté gauche) étant un objet et le cas spécifique du type statique (type / RHS) étant une chaîne. Et touche bien à l'internement de cordes.
barlop
2
@badsamaritan En raison de l'internement de chaînes
Alexander Derck
46

==et .Equalsdépendent tous deux du comportement défini dans le type réel et le type réel sur le site d'appel. Les deux ne sont que des méthodes / opérateurs qui peuvent être remplacés sur n'importe quel type et compte tenu du comportement souhaité par l'auteur. D'après mon expérience, je trouve qu'il est courant pour les gens d'implémenter .Equalssur un objet mais néglige d'implémenter l'opérateur ==. Cela signifie que .Equalsva réellement mesurer l'égalité des valeurs tout ==en mesurant si elles sont ou non la même référence.

Lorsque je travaille avec un nouveau type dont la définition est en flux ou que j'écris des algorithmes génériques, je trouve que la meilleure pratique est la suivante

  • Si je veux comparer des références en C #, j'utilise Object.ReferenceEqualsdirectement (pas nécessaire dans le cas générique)
  • Si je veux comparer les valeurs que j'utilise EqualityComparer<T>.Default

Dans certains cas, lorsque je pense que l'utilisation de ==est ambigu, j'utiliserai explicitement Object.Referenceégal dans le code pour supprimer l'ambiguïté.

Eric Lippert a récemment publié un article sur le blog expliquant pourquoi il existe 2 méthodes d'égalité dans le CLR. Ça vaut le coup d'être lu

JaredPar
la source
Eh bien Jared, vous violez directement le fameux "Le meilleur code de Jeff n'est pas du tout ici." Est-ce vraiment justifié? D'un autre côté, je peux voir d'où cela vient et pourquoi il pourrait être souhaitable de rendre la sémantique explicite. Dans ce cas, je préfère de loin la façon dont VB traite de l'égalité des objets. C'est court et sans ambiguïté.
Konrad Rudolph
@ Konrad, j'aurais vraiment dû dire "quand je ne suis pas familier avec un type, je trouve que la meilleure pratique est la suivante". Oui, VB a une bien meilleure sémantique ici car il sépare vraiment l'égalité de valeur et de référence. C # mélange les deux et provoque parfois des erreurs d'ambiguïté.
JaredPar
10
Ce n'est pas tout à fait vrai. == ne peut pas être remplacé, c'est une méthode statique. Il ne peut être surchargé, ce qui est une différence importante. Ainsi, le code qui est exécuté pour un opérateur == est lié au moment de la compilation, tandis que Equals est virtuel et trouvé au moment de l'exécution.
Stefan Steinegger
20

== Opérateur

  1. Si les opérandes sont des types de valeur et que leurs valeurs sont égales, elle renvoie vrai sinon faux.
  2. Si les opérandes sont des types de référence à l'exception de la chaîne et que les deux font référence à la même instance (même objet), elle renvoie true sinon false.
  3. Si les opérandes sont de type chaîne et que leurs valeurs sont égales, elle renvoie vrai sinon faux.

.Équivaut à

  1. Si les opérandes sont des types de référence , il exécute l' égalité de référence, c'est-à-dire que si les deux font référence à la même instance (même objet), il renvoie vrai sinon faux.
  2. Si les opérandes sont des types de valeur, contrairement à l'opérateur ==, il vérifie d'abord leur type et si leurs types sont identiques, il exécute l'opérateur ==, sinon il renvoie false.
kashif
la source
2
Ce n'est pas correct. L' ==opérateur peut être surchargé pour tout type, pas seulement pour la chaîne. La description d'une exception de cas spécial uniquement pour la chaîne représente de manière erronée la sémantique de l'opérateur. Il serait plus précis, mais peut-être pas terriblement utile, de dire "si les opérandes sont des types de référence, il renvoie vrai si les opérandes se réfèrent au même objet, sauf en cas de surcharge applicable, auquel cas l'implémentation de cette surcharge détermine le résultat ". Il en va de même pour Equalsla complication supplémentaire qu'il s'agit d'une méthode virtuelle, de sorte que son comportement peut être outrepassé et surchargé.
phoog
19

Premièrement, il y a une différence. Pour les chiffres

> 2 == 2.0
True

> 2.Equals(2.0)
False

Et pour les cordes

> string x = null;
> x == null
True

> x.Equals(null)
NullReferenceException

Dans les deux cas, ==se comporte plus utilement que.Equals

Colonel Panic
la source
2
Je ne suis pas sûr que je considérerais la contrainte des types intégraux aux types à virgule flottante avec l' ==opérateur comme une bonne chose. Par exemple, 16777216.0f doit-il être égal à (int) 16777217, (double) 16777217.0, les deux ou ni l'un ni l'autre? Les comparaisons entre les types intégraux sont bonnes, mais les comparaisons à virgule flottante ne doivent être effectuées qu'à mon humble avis avec des valeurs explicitement converties en types correspondants. La comparaison de a floatà quelque chose d'autre que a float, ou de doubleà quelque chose d'autre que a double, me semble être une odeur de code majeure qui ne devrait pas être compilée sans diagnostic.
supercat
1
@supercat Je suis d'accord - c'est pénible qui x == yn'implique pas x/3 == y/3(essayez x = 5et y = 5.0).
Colonel Panic
Je considère que l'utilisation de la /division entière est un défaut dans la conception de C # et Java. divLes ` are much better. The problems with == `de Pascal et même de VB.NET sont pires, cependant: x==yet y==zcela n'implique pas cela x==z(considérez les trois nombres dans mon commentaire précédent). Quant à la relation que vous suggérez, même si xet ysont les deux floatou les deux double, x.equals((Object)y)n'implique pas que 1.0f/x == 1.0f / y` (si j'avais mes druthers, cela garantirait cela; même si ==ne fait pas de distinction entre le positif et le zéro, Equalsdevrait).
supercat
C'est normal, car le premier paramètre d'Equals () est une chaîne!
Whiplash
17

Pour autant que je le comprends, la réponse est simple:

  1. == compare les références d'objet.
  2. .Equals compare le contenu de l'objet.
  3. String les types de données agissent toujours comme une comparaison de contenu.

J'espère que j'ai raison et qu'il a répondu à votre question.

Liraz Shaka Amir
la source
15

J'ajouterais que si vous transformez votre objet en chaîne, cela fonctionnera correctement. C'est pourquoi le compilateur vous donnera un avertissement disant:

Comparaison de référence involontaire possible; pour obtenir une comparaison de valeurs, placez le côté gauche pour taper 'chaîne'

MikeKulls
la source
1
Exactement. @DominicCronin: respectez toujours les avertissements à la compilation. Si c'est le cas object expr = XXX; if (expr == "Energy") { ... }, le côté gauche étant de type objectcompilation, le compilateur doit utiliser la surcharge operator ==(object, object). Il vérifie l'égalité de référence. Si cela donnera trueou falsepeut être difficile à prévoir en raison de l' internement de chaînes . Si vous savez que le côté gauche est nullde type ou de type string, lancez le côté gauche sur stringavant de l'utiliser ==.
Jeppe Stig Nielsen
de mettre une partie de cela d'une autre manière. == (pour déterminer s'il utilise l'égalité de référence ou l'égalité de valeur) dépend du type de temps de compilation / type statique / type de gauche. (c'est le type qui est résolu dans une analyse de temps de compilation). Plutôt que le type d'exécution / type dynamique / type RHS. Le code de BlueMonkMN le montre, mais pas avec le casting.
barlop
5

Étant donné que la version statique de la .Equalméthode n'a pas été mentionnée jusqu'à présent, je voudrais l'ajouter ici pour résumer et comparer les 3 variantes.

MyString.Equals("Somestring"))          //Method 1
MyString == "Somestring"                //Method 2
String.Equals("Somestring", MyString);  //Method 3 (static String.Equals method) - better

MyStringest une variable qui vient d'ailleurs dans le code.

Informations de fond et pour résumer:

En Java, utiliser ==pour comparer les chaînes ne doit pas être utilisé. Je mentionne cela au cas où vous auriez besoin d'utiliser les deux langues et aussi pour vous faire savoir que l'utilisation ==peut également être remplacée par quelque chose de mieux en C #.

En C #, il n'y a pas de différence pratique pour comparer des chaînes en utilisant la méthode 1 ou la méthode 2 tant que les deux sont de type chaîne. Cependant, si l'un est nul, l'un est d'un autre type (comme un entier), ou l'un représente un objet qui a une référence différente, alors, comme le montre la question initiale, vous pouvez rencontrer que la comparaison du contenu pour l'égalité peut ne pas retourner ce que vous vous attendez.

Solution suggérée:

Étant donné que l'utilisation ==n'est pas exactement la même chose que .Equalslors de la comparaison, vous pouvez utiliser la méthode statique String.Equals à la place. De cette façon, si les deux côtés ne sont pas du même type, vous comparerez toujours le contenu et si l'un est nul, vous éviterez l'exception.

   bool areEqual = String.Equals("Somestring", MyString);  

C'est un peu plus à écrire, mais à mon avis, plus sûr à utiliser.

Voici quelques informations copiées de Microsoft:

public static bool Equals (string a, string b);

Paramètres

a Chaîne

La première chaîne à comparer, ou null.

b Chaîne

La deuxième chaîne à comparer, ou null.

Retour Boolean

truesi la valeur de aest la même que la valeur de b; autrement, false. Si les deux aet le bsont null, la méthode retourne true.

Mario Levesque
la source
5

Tout comme un ajout aux réponses déjà bonnes: ce comportement n'est PAS limité aux chaînes ou à la comparaison de différents types de chiffres. Même si les deux éléments sont de type objet du même type sous-jacent. "==" ne fonctionnera pas.

La capture d'écran suivante montre les résultats de la comparaison de deux valeurs d'objet {int} -

Exemple de VS2017

Ole Albers
la source
2

Je suis un peu confus ici. Si le type d'exécution de Content est de type chaîne, alors == et Equals doivent renvoyer true. Cependant, étant donné que cela ne semble pas être le cas, le type d'exécution du contenu n'est pas une chaîne et appeler Equals dessus fait une égalité référentielle et cela explique pourquoi Equals ("Energy Attack") échoue. Cependant, dans le second cas, la décision quant à l'opérateur statique == surchargé à appeler est prise au moment de la compilation et cette décision semble être == (chaîne, chaîne). cela me suggère que le contenu fournit une conversion implicite en chaîne.

Mehmet Aras
la source
2
Vous l'avez dos à l'avant. Pour un début égal ("Energy Attack") n'échoue pas, == est celui qui retourne faux. Le == échoue car il utilise le == de l'objet, pas la chaîne.
MikeKulls
Par défaut, l'opérateur == teste l'égalité des références en déterminant si deux références indiquent le même objet. Par conséquent, les types de référence n'ont pas à implémenter l'opérateur == pour obtenir cette fonctionnalité. Lorsqu'un type est immuable, c'est-à-dire que les données contenues dans l'instance ne peuvent pas être modifiées, la surcharge de l'opérateur == pour comparer l'égalité de valeur au lieu de l'égalité de référence peut être utile car, en tant qu'objets immuables, elles peuvent être considérées comme les mêmes tant que car ils ont la même valeur. Ce n'est pas une bonne idée de remplacer l'opérateur == dans les types non immuables.
Wajeed-MSFT
2

Il y a une autre dimension à une réponse antérieure de @BlueMonkMN. La dimension supplémentaire est que la réponse à la question du titre de @ Drahcir telle qu'elle est énoncée dépend également de la façon dont nous sommes arrivés à la stringvaleur. Pour illustrer:

string s1 = "test";
string s2 = "test";
string s3 = "test1".Substring(0, 4);
object s4 = s3;
string s5 = "te" + "st";
object s6 = s5;
Console.WriteLine("{0} {1} {2}", object.ReferenceEquals(s1, s2), s1 == s2, s1.Equals(s2));

Console.WriteLine("\n  Case1 - A method changes the value:");
Console.WriteLine("{0} {1} {2}", object.ReferenceEquals(s1, s3), s1 == s3, s1.Equals(s3));
Console.WriteLine("{0} {1} {2}", object.ReferenceEquals(s1, s4), s1 == s4, s1.Equals(s4));

Console.WriteLine("\n  Case2 - Having only literals allows to arrive at a literal:");
Console.WriteLine("{0} {1} {2}", object.ReferenceEquals(s1, s5), s1 == s5, s1.Equals(s5));
Console.WriteLine("{0} {1} {2}", object.ReferenceEquals(s1, s6), s1 == s6, s1.Equals(s6));

La sortie est:

True True True

  Case1 - A method changes the value:
False True True
False False True

  Case2 - Having only literals allows to arrive at a literal:
True True True
True True True
Novichok
la source
2

Ajout d'un point de plus à la réponse.

.EqualsTo() La méthode vous permet de comparer la culture et la casse.

Bala
la source
0

Le ==jeton en C # est utilisé pour deux opérateurs de vérification d'égalité différents. Lorsque le compilateur rencontre ce jeton, il vérifie si l'un des types comparés a implémenté une surcharge d'opérateur d'égalité pour les types de combinaison spécifiques comparés (*) ou pour une combinaison de types vers lesquels les deux types peuvent être convertis. Si le compilateur trouve une telle surcharge, il l'utilisera. Sinon, si les deux types sont tous les deux des types de référence et qu'ils ne sont pas des classes non liées (soit il peut s'agir d'une interface, soit de classes liées), le compilateur considérera ==comme un opérateur de comparaison de référence. Si aucune des conditions ne s'applique, la compilation échouera.

Notez que certaines autres langues utilisent des jetons distincts pour les deux opérateurs de vérification d'égalité. Dans VB.NET, par exemple, le =jeton est utilisé dans les expressions uniquement pour l'opérateur de vérification d'égalité surchargeable et Isest utilisé comme opérateur de test de référence ou de test nul. Un à utiliser =sur un type qui ne remplace pas l'opérateur de vérification d'égalité échouera, de même que la tentative d'utilisation Isà d'autres fins que le test d'égalité ou de nullité de référence.

(*) Les types ne surchargent généralement l'égalité que pour la comparaison avec eux-mêmes, mais il peut être utile pour les types de surcharger l'opérateur d'égalité pour la comparaison avec d'autres types particuliers; par exemple, intaurait pu (et floatà mon humble avis aurait dû mais pas) défini un opérateur d'égalité à comparer , de sorte que 16777217 ne se rapporterait pas égal à 16777216f. En l'état, étant donné qu'aucun opérateur de ce type n'est défini, C # promeut le intto floaten l'arrondissant à 16777216f avant que l'opérateur de vérification d'égalité ne le voit; cet opérateur voit alors deux nombres à virgule flottante égaux et les signale comme égaux, ignorant l'arrondi qui a eu lieu.

supercat
la source
Plutôt que d'avoir une comparaison int-à-flottant renvoyer false, je préfère l'approche que F # utilise, qui consiste à interdire une telle comparaison. Le programmeur peut alors décider si et comment gérer le fait que les valeurs ont un type différent. Parce que parfois, après tout, nous ne voulons traiter 3comme étant égal 3.0f. Si nous demandons au programmeur de dire ce qui est prévu dans tous les cas, il n'y a aucun danger de comportement par défaut conduisant à des résultats inattendus, car il n'y a pas de comportement par défaut.
phoog
@phoog: Mon sentiment personnel est que les langues devraient avoir leurs moyens "normaux" de test d'égalité implémenter une relation d'équivalence et interdire toutes les combinaisons d'opérandes pour lesquelles cela ne serait pas le cas. Je ne vois pas un énorme avantage d'avoir une égalité de vérification de langue entre les entiers et les flottants en confirmant qu'un flottant représente précisément un nombre entier qui correspond à l'int, par rapport à simplement interdire de telles comparaisons, mais considérerais l'une ou l'autre approche supérieure à la performance du langage une conversion avec perte avant la comparaison.
supercat
0

Des réponses et des exemples vraiment géniaux!

Je voudrais juste ajouter la différence fondamentale entre les deux,

Les opérateurs tels que ==ne sont pas polymorphes, tout Equalsest

Avec ce concept à l'esprit, si vous travaillez sur un exemple (en regardant le type de référence à gauche et à droite, et en vérifiant / sachant si le type a effectivement == opérateur surchargé et égal à étant remplacé), vous êtes certain d'obtenir la bonne réponse .

Manish Basantani
la source
-1

Lorsque nous créons un objet, l'objet est divisé en deux parties, l'une est le contenu et l'autre fait référence à ce contenu. ==compare à la fois le contenu et la référence; equals()compare uniquement le contenu

http://www.codeproject.com/Articles/584128/What-is-the-difference-between-equalsequals-and-Eq

user3440463
la source
1
Ce n'est pas vrai. Si aet bsont tous deux des références de chaîne, le résultat de a == bne dépend pas du fait que les références pointent vers le même objet.
phoog
-2

==

L'opérateur == peut être utilisé pour comparer deux variables de toute nature, et il compare simplement les bits .

int a = 3;
byte b = 3;
if (a == b) { // true }

Remarque: il y a plus de zéros sur le côté gauche de l'int, mais nous ne nous en soucions pas ici.

int a (00000011) == octet b (00000011)

Rappelez-vous que l'opérateur == ne se soucie que du modèle des bits de la variable.

Utilisez == si deux références (primitives) font référence au même objet sur le tas.

Les règles sont les mêmes que la variable soit une référence ou une primitive.

Foo a = new Foo();
Foo b = new Foo();
Foo c = a;

if (a == b) { // false }
if (a == c) { // true }
if (b == c) { // false }

a == c est vrai a == b est faux

le motif binaire est le même pour a et c, ils sont donc égaux en utilisant ==.

Égal():

Utilisez la méthode equals () pour voir si deux objets différents sont égaux .

Tels que deux objets String différents qui représentent tous les deux les personnages de "Jane"

Sanchit
la source
2
Ceci est une erreur. Considérez ce qui suit: object a = 3; object b = 3; Console.WriteLine(a == b);. La sortie est fausse, même si les modèles binaires des valeurs sont les mêmes. Les types d'opérandes importent également. La raison pour laquelle nous "ne nous soucions pas" du nombre différent de zéros dans votre exemple est qu'au moment où nous appelons l'opérateur égal, le nombre de zéros est en fait le même , en raison de la conversion implicite.
phoog
-2

La seule différence entre Equal et == réside dans la comparaison des types d'objets. dans d'autres cas, tels que les types de référence et les types de valeurs, ils sont presque identiques (les deux sont une égalité bit à bit ou les deux une égalité de référence).

objet: égal à: égalité bit à bit ==: égalité de référence

chaîne: (égal et == sont les mêmes pour la chaîne, mais si l'une des chaînes a changé en objet, le résultat de la comparaison sera différent) Égale: égalité bit à bit ==: égalité bit à bit

Voir ici pour plus d'explications.

Will Yu
la source
Object.Equals ne considère pas nécessairement l'égalité au niveau du bit. C'est une méthode virtuelle, et un remplacement peut faire ce qu'il veut.
phoog
oui, vous avez raison, vous pouvez faire tout ce que vous voulez pour le remplacer. mais le sujet dont nous parlons est l'implémentation par défaut. l'implémentation par défaut d'Object.Equals est l'égalité au niveau du bit.
Will Yu