Question

J'ai une condition dans une application silverlight qui compare deux chaînes. Pour une raison quelconque, lorsque j'utilise == , il renvoie false avec .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
}

Avez-vous une raison de le faire?

Était-ce utile?

La solution

Lorsque == est utilisé sur une expression de type objet , la résolution est System.Object.ReferenceEquals .

est égal à est simplement un < code> virtual et se comporte comme tel, la version remplacée sera donc utilisée (qui, pour le type string compare le contenu).

Autres conseils

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), est égal à compare les valeurs , tandis que == compare les références d'objet . Si deux objets que vous comparez font référence à la même instance exacte d'un objet, ils renverront tous les deux la valeur true, mais si l'un d'entre eux a le même contenu et provient d'une source différente (est une instance séparée avec les mêmes données), seul Equals retourne vrai. Cependant, comme indiqué dans les commentaires, chaîne constitue un cas particulier, car elle remplace l'opérateur == . Ainsi, 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 si sont des instances séparées. Le code suivant illustre les différences subtiles dans les 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));

Le résultat est:

True True True
False True True
False False True

== et .Equals dépendent tous deux du comportement défini dans le type réel et du type réel sur le site d'appel. Les deux ne sont que des méthodes / opérateurs qui peuvent être remplacés par tout type et tout comportement souhaité par l'auteur. D'après mon expérience, il est courant que les gens implémentent .Equals sur un objet, mais négligent d'implémenter l'opérateur == . Cela signifie que .Equals va réellement mesurer l’égalité des valeurs tandis que == va mesurer si elles sont ou non la même référence.

Lorsque je travaille avec un nouveau type dont la définition est en train de changer ou d'écrire 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 directement Object.ReferenceEquals (inutile dans le cas générique)
  • Si je souhaite comparer des valeurs, j'utilise EqualityComparer < T > .Default

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

Eric Lippert a récemment publié un article sur son blog expliquant pourquoi il existe deux méthodes d’égalité dans le CLR. Ça vaut le coup de lire

Tout d'abord, il y a une une différence. Pour les chiffres

> 2 == 2.0
True

> 2.Equals(2.0)
False

Et pour les chaînes

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

> x.Equals(null)
NullReferenceException

Dans les deux cas, == se comporte mieux que .Equals

J'ajouterais que si vous convertissez votre objet en chaîne, celui-ci fonctionnera correctement. C’est pourquoi le compilateur vous avertit:

  

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

== Opérateur 1. Si les opérandes sont Types de valeur et que leurs valeurs sont égales, le résultat est renvoyé. vrai sinon faux. 2. Si les opérandes sont Types de référence à l'exception de chaîne et font référence à même objet, il retourne vrai sinon faux. 3. Si les opérandes sont de type chaîne et que leurs valeurs sont égales, la valeur renvoyée est true sinon false.

.Equals 1. Si les opérandes sont des types de référence, il effectue une égalité de référence si tous deux se réfèrent au même objet, il retourne true sinon false. 2. Si les opérandes sont des types de valeur, alors, contrairement à l'opérateur ==, il vérifie d'abord leur type et si leur type est identique, il exécute l'opérateur ==, sinon il renvoie false.

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

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

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

La version statique de la méthode .Equal n'ayant pas été mentionnée jusqu'à présent, j'aimerais 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

MyString est une variable qui provient d'un autre endroit du code.

Informations de base et résumé:

En Java, l'utilisation de == pour comparer des chaînes ne doit pas être utilisée. Je le mentionne au cas où vous devriez utiliser les deux langues et aussi pour vous informer que l'utilisation de == peut également être remplacée par quelque chose de meilleur en C #.

En C #, il n'y a pas de différence pratique pour comparer des chaînes à l'aide de la Méthode 1 ou de la Méthode 2 tant que les deux sont de type chaîne. Cependant, si l'une est nulle, si elle est d'un autre type (comme un entier) ou si elle représente un objet ayant une référence différente, alors, comme le montre la question initiale, vous pouvez vous rendre compte que la comparaison du contenu pour l'égalité ne renvoie pas ce que vous vous attendez.

Solution suggérée:

Parce que l'utilisation de == n'est pas exactement la même chose que d'utiliser .Equals lors de la comparaison d'éléments, vous pouvez utiliser la méthode static String.Equals . au lieu. De cette façon, si les deux côtés ne sont pas du même type, vous comparerez quand même le contenu et si l'un d'entre eux est null, vous éviterez l'exception.

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

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

Voici quelques informations copiées à partir de Microsoft:

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

Paramètres

une chaîne

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

b Chaîne

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

Renvoie Boolean

true si la valeur de a est identique à la valeur de b ; sinon, false . Si a et b sont null , la méthode retourne true .

Je suis un peu confus ici. Si le type de contenu d'exécution est de type chaîne, alors == et Equals doivent renvoyer true. Toutefois, comme cela ne semble pas être le cas, le type de contenu d'exécution n'est pas une chaîne et l'appel d'Equal sur une égalité référentielle lui permet de réaliser une égalité référentielle, ce qui explique pourquoi Echals ("Energy Attack") échoue. Toutefois, dans le second cas, la décision relative à l'opérateur appelé == statique surchargé est prise au moment de la compilation et cette décision semble être == (chaîne, chaîne). cela me suggère que Content fournit une conversion implicite en chaîne.

Il y a une autre dimension à une réponse antérieure de @BlueMonkMN. La dimension supplémentaire est que la réponse à la question de titre de @ Drahcir, telle qu’elle est énoncée, dépend également de comment nous sommes arrivés à la valeur chaîne . 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));

Le résultat 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

Ajouter un point de plus à la réponse.

La méthode

.EqualsTo () vous permet de comparer la culture et la casse.

Juste comme un ajout aux bonnes réponses: ce comportement n'est PAS limité aux chaînes ou à la comparaison de différents types numériques. 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 {int} d'objet

 Exemple de VS2017

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 laquelle les deux types peuvent être convertis. Si le compilateur trouve une telle surcharge, il l'utilisera. Sinon, si les deux types sont tous deux des types de référence et qu'ils ne sont pas des classes sans rapport (soit une interface, soit des classes liées), le compilateur considérera == comme un opérateur de comparaison de références. . Si aucune des deux conditions ne s'applique, la compilation échouera.

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

(*) Les types ne surchargent généralement que l'égalité pour la comparaison avec eux-mêmes, mais il peut être utile que les types surchargent l'opérateur d'égalité pour la comparaison avec d'autres types particuliers; Par exemple, int pourrait avoir (et IMHO devrait mais ne l'a pas fait) défini des opérateurs d'égalité pour la comparaison avec float , de sorte que 16777217 ne se signale pas comme étant égal à 16777216f. En l’état, puisqu’aucun opérateur de ce type n’est défini, C # promeut int en float , en l’arrondissant à 16777216f avant que l’opérateur de contrôle d’égalité ne le voie; cet opérateur voit ensuite deux nombres à virgule flottante égaux et les signale égaux, ignorant l'arrondi qui a eu lieu.

Vraiment d'excellentes réponses et exemples!

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

  

Les opérateurs tels que == ne sont pas polymorphes, alors que est égal à est

.

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

Lorsque nous créons un objet, celui-ci comprend deux parties: le contenu et l’autre, une référence à ce contenu. == compare 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

==

L'opérateur == peut être utilisé pour comparer deux variables de tout type. Il compare simplement les bits .

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

Remarque: il y a plus de zéros à gauche de l'int, mais on s'en fiche de ça ici.

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

N'oubliez pas == l'opérateur se soucie uniquement de la structure des bits de la variable.

Utilisation == 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

les configurations de bits sont les mêmes pour a et c, elles sont donc égales avec ==.

Equal ():

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

Par exemple, deux objets String différents représentant les caractères de "Jane"

.

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

objet: Égale: égalité au niveau des bits ==: égalité de référence

chaîne: (égal à == sont identiques pour chaîne, mais si l'une des chaînes est remplacée par objet, le résultat de la comparaison sera différent) Égale: égalité au niveau des bits ==: égalité au niveau des bits

Voir ici pour plus d'explications.

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top