Pregunta

Tengo una condición en una aplicación de Silverlight que compara 2 cadenas, por alguna razón, cuando uso == devuelve false mientras que .Equals () devuelve true .

Aquí está el código:

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

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

¿Alguna razón por la que esto esté sucediendo?

¿Fue útil?

Solución

Cuando == se usa en una expresión de tipo objeto , se resolverá como System.Object.ReferenceEquals .

Equals es solo un < código> virtual y se comporta como tal, por lo que se usará la versión anulada (que, para el tipo cadena compara el contenido).

Otros consejos

Al comparar una referencia de objeto con una cadena (incluso si la referencia de objeto se refiere a una cadena), se ignora el comportamiento especial del operador == específico de la clase de cadena.

Normalmente (cuando no se trata de cadenas, es decir), Equals compara valores , mientras que == compara referencias de objeto . Si dos objetos que está comparando se refieren a la misma instancia exacta de un objeto, ambos devolverán el valor verdadero, pero si uno tiene el mismo contenido y proviene de una fuente diferente (es una instancia separada con los mismos datos), solo los iguales volver verdadero Sin embargo, como se señaló en los comentarios, la cadena es un caso especial porque reemplaza al operador == , de modo que cuando se trata exclusivamente de referencias de cadena (y no de referencias de objeto), solo se comparan los valores, incluso si Son instancias separadas. El siguiente código ilustra las diferencias sutiles en los comportamientos:

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 salida es:

True True True
False True True
False False True

== y .Equals dependen del comportamiento definido en el tipo real y del tipo real en el sitio de la llamada. Ambos son solo métodos / operadores que pueden ser anulados en cualquier tipo y dado el comportamiento que el autor desee. En mi experiencia, creo que es común que las personas implementen .Equals en un objeto, pero se niegan a implementar el operador == . Esto significa que .Equals realmente medirá la igualdad de los valores, mientras que == medirá si son o no la misma referencia.

Cuando trabajo con un nuevo tipo cuya definición está en flujo o escribiendo algoritmos genéricos, creo que la mejor práctica es la siguiente

  • Si quiero comparar referencias en C #, uso Object.ReferenceEquals directamente (no es necesario en el caso genérico)
  • Si quiero comparar valores, uso EqualityComparer<T>.Default

En algunos casos, cuando siento que el uso de == es ambiguo, usaré explícitamente Object.Reference en el código para eliminar la ambigüedad.

Eric Lippert recientemente hizo una publicación en el blog sobre el tema de por qué hay 2 métodos de igualdad en el CLR. Vale la pena la lectura

En primer lugar, hay una diferencia. Para números

> 2 == 2.0
True

> 2.Equals(2.0)
False

Y para cuerdas

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

> x.Equals(null)
NullReferenceException

En ambos casos, == se comporta de manera más útil que .Equals

Yo agregaría que si convierte su objeto en una cadena, entonces funcionará correctamente. Esta es la razón por la cual el compilador le dará una advertencia diciendo:

  

Posible comparación de referencia involuntaria; para obtener una comparación de valores,   lanzar el lado izquierdo para escribir 'cadena'

== Operador 1. Si los operandos son Tipos de valor y sus valores son iguales, devuelve cierto más falso. 2. Si los operandos son Tipos de referencia con excepción de la cadena y ambos se refieren a mismo objeto, devuelve true o false. 3. Si los operandos son de tipo cadena y sus valores son iguales, devuelve true o false.

.Equals 1. Si los operandos son tipos de referencia, realiza Igualdad de referencia eso es si ambos se refieren al mismo objeto, devuelve verdadero o falso. 2. Si los operandos son tipos de valor, a diferencia del operador ==, primero verifica su tipo y si sus tipos son los mismos, el operador == devuelve falso.

Por lo que yo entiendo, la respuesta es simple:

  1. == compara referencias de objetos.
  2. .Equals compara el contenido del objeto.
  3. Los tipos de datos de cadena siempre actúan como una comparación de contenido.

Espero estar en lo correcto y que haya respondido a tu pregunta.

Debido a que la versión estática del método .Equal no se mencionó hasta ahora, me gustaría agregar esto aquí para resumir y comparar las 3 variaciones.

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

donde MyString es una variable que proviene de otra parte del código.

Información de fondo y para resumir:

En Java usando == para comparar cadenas no se debe usar. Menciono esto en caso de que necesite usar ambos idiomas y también para hacerle saber que usar == también se puede reemplazar con algo mejor en C #.

En C # no hay una diferencia práctica para comparar cadenas utilizando el Método 1 o el Método 2 siempre que ambos sean de tipo cadena. Sin embargo, si uno es nulo, uno es de otro tipo (como un número entero), o uno representa un objeto que tiene una referencia diferente, entonces, como muestra la pregunta inicial, puede experimentar que comparar el contenido para la igualdad puede no devolver lo que usted espera.

Solución sugerida:

Debido a que usar == no es exactamente lo mismo que usar .Equals al comparar cosas, puede usar el método static String.Equals en lugar. De esta manera, si los dos lados no son del mismo tipo, seguirá comparando el contenido y si uno es nulo, evitará la excepción.

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

Es un poco más para escribir, pero en mi opinión, más seguro de usar.

Aquí hay alguna información copiada de Microsoft:

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

Parámetros

a String

La primera cadena para comparar, o null .

b String

La segunda cadena a comparar, o null .

Devuelve Boolean

true si el valor de a es el mismo que el valor de b ; de lo contrario, false . Si tanto a como b son null , el método devuelve true .

Estoy un poco confundido aquí. Si el tipo de Contenido en tiempo de ejecución es de tipo cadena, entonces tanto == como Equals deberían devolver verdadero. Sin embargo, dado que este no parece ser el caso, entonces el tipo de Contenido en tiempo de ejecución no es una cadena y llamar a Igualdad está haciendo una igualdad referencial y esto explica por qué falla la Igualdad (" Ataque de Energía "). Sin embargo, en el segundo caso, la decisión sobre a qué operador estático == sobrecargado se debe llamar se toma en el momento de la compilación y esta decisión parece ser == (cadena, cadena). esto me sugiere que el Contenido proporciona una conversión implícita a cadena.

Hay otra dimensión en una respuesta anterior por @BlueMonkMN. La dimensión adicional es que la respuesta a la pregunta del título de @ Drahcir tal como se establece también depende de cómo llegamos al valor de string . Para ilustrar:

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 salida es:

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

Agregando un punto más a la respuesta.

El método

.EqualsTo () le brinda la posibilidad de compararlo con la cultura y distingue entre mayúsculas y minúsculas.

Solo como una adición a las ya buenas respuestas: este comportamiento NO está limitado a cadenas o comparando diferentes tipos de números. Incluso si ambos elementos son de tipo objeto del mismo tipo subyacente. " == " no funcionará.

La siguiente captura de pantalla muestra los resultados de la comparación de dos objetos {int} - valores

 Ejemplo de VS2017

El token == en C # se usa para dos operadores de verificación de igualdad diferentes. Cuando el compilador se encuentra con ese token, verificará si alguno de los tipos que se comparan ha implementado una sobrecarga de operador de igualdad para los tipos de combinación específicos que se comparan (*), o para una combinación de tipos a los que se pueden convertir ambos tipos. Si el compilador encuentra tal sobrecarga, la usará. De lo contrario, si los dos tipos son tipos de referencia y no son clases no relacionadas (o bien puede ser una interfaz o clases relacionadas), el compilador considerará a == como un operador de comparación de referencia . Si no se aplica ninguna condición, la compilación fallará.

Tenga en cuenta que algunos otros idiomas usan tokens separados para los dos operadores de verificación de igualdad. En VB.NET, por ejemplo, el token = se usa en expresiones únicamente para el operador de verificación de igualdad sobrecargable, y Is se usa como prueba de referencia o nulo operador de prueba El uso de = en un tipo que no anule al operador de verificación de igualdad fallará, al igual que intentar usar Is para cualquier otro propósito que no sea probar la igualdad o nulidad de referencia.

(*) Los tipos generalmente solo sobrecargan la igualdad para la comparación con ellos mismos, pero puede ser útil para los tipos sobrecargar al operador de la igualdad para la comparación con otros tipos particulares; por ejemplo, int podría haber (y IMHO debería haber definido, pero no lo hizo) un operador de igualdad para comparar con float , de modo que 16777217 no se reportaría igual a 16777216f. Tal como está, dado que no se define tal operador, C # promocionará int a float , redondeando a 16777216f antes de que el operador de verificación de igualdad lo vea; ese operador ve dos números de punto flotante iguales y los informa como iguales, sin darse cuenta del redondeo que tuvo lugar.

¡Respuestas y ejemplos realmente geniales!

Me gustaría añadir la diferencia fundamental entre los dos,

  

Los operadores como == no son polimórficos, mientras que Equals es

Teniendo en cuenta ese concepto, si resuelve algún ejemplo (mirando el tipo de referencia de la mano izquierda y la mano derecha, y comprobando / sabiendo si el tipo realmente tiene == operador sobrecargado e Igualdad omitida) es seguro que obtendrá La respuesta correcta.

Cuando creamos cualquier objeto, el objeto tiene dos partes, una es el contenido y la otra es la referencia a ese contenido. == compara el contenido y la referencia; es igual a () compara solo contenido

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

==

El operador == puede utilizarse para comparar dos variables de cualquier tipo, y simplemente compara los bits .

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

Nota: hay más ceros en el lado izquierdo del int pero no nos importa eso aquí.

int a (00000011) == byte b (00000011)

Recuerde que el operador == solo se preocupa por el patrón de los bits en la variable.

Use == Si dos referencias (primitivas) se refieren al mismo objeto en el montón.

Las reglas son las mismas si la variable es una referencia o una primitiva.

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 es verdadero a == b es falso

el patrón de bits es el mismo para a y c, por lo que son iguales usando ==.

Equal():

Use el método equals () para ver si dos objetos diferentes son iguales .

Como dos objetos String diferentes que representan los caracteres en " Jane "

La única diferencia entre Igual y == es en la comparación de tipo de objeto. en otros casos, como los tipos de referencia y los tipos de valor, son casi los mismos (ambos son iguales a nivel de bits o ambos son iguales).

objeto: Igual a la igualdad de bits ==: igualdad de referencia

cadena: (igual y == son iguales para la cadena, pero si una de la cadena cambia a objeto, el resultado de la comparación será diferente) Igual a la igualdad de bits ==: igualdad de bits

Consulte aquí para obtener más información.

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top