objects - equals c# ejemplos
¿Diferencia entre el operador== y el método Equals() en C#? (3)
¿Cuál es la diferencia entre ==
y Equals()
con el ejemplo? Sé que se usa ==
para comparar el operador y se usa el método Equals()
para comparar el contenido de la cadena. Así que lo intenté
// first example
string s1 = "a";
string s2 = "a";
Console.Write(a.Equals(s2)); // returns true, but if I assign "b" to s2,
// then result will be false
// second example
string s1 ="a";
string s2 ="a";
Console.Write(s1 == s2); // returns true
¿Cómo es esto? Ambas son referencias de objetos diferentes. Supongamos que consideramos que estos son de referencia. Pero traté de usar así
string s1 = new string("ab");
string s2 = new string("ab");
Estoy obteniendo un error de tiempo de compilación que no puede convertir una cadena a char
Cita de la documentación de Equals :
La implementación predeterminada de Equals admite la igualdad de referencia para los tipos de referencia y la igualdad a nivel de bits para los tipos de valor. Igualdad de referencia significa que las referencias de objetos que se comparan se refieren al mismo objeto. Igualdad de bits significa que los objetos que se comparan tienen la misma representación binaria.
Y el operador == :
Para tipos de valores predefinidos, el operador de igualdad (==) devuelve verdadero si los valores de sus operandos son iguales, de lo contrario, falso. Para tipos de referencia distintos a la cadena, == devuelve verdadero si sus dos operandos se refieren al mismo objeto. Para el tipo de cadena, == compara los valores de las cadenas.
Ahora volvamos a tu pregunta: ¿por qué s1 == s2
devuelve true? Las cuerdas son bestias especiales en .NET. Representan tipos de referencia inmutables. Están internados en .NET. Esto significa que si tiene 2 constantes de cadena con el mismo valor, se referirán a la misma instancia de objeto en tiempo de ejecución.
Cita de la documentation :
El Common Language Runtime conserva el almacenamiento de cadenas manteniendo una tabla, llamada grupo interno, que contiene una única referencia a cada cadena literal única declarada o creada mediante programación en su programa. En consecuencia, una instancia de una cadena literal con un valor particular solo existe una vez en el sistema.
Estás pensando que parece Java-esque. En java, el operador ==
no se puede personalizar, por lo que para los tipos de referencia, siempre significa igualdad de referencia, mientras que significa igualdad de valor para los tipos primitivos. Por otro lado, Equals
es para verificar la igualdad de valores en los tipos de referencia.
Sin embargo, las cosas son diferentes en C #. Ambos Equals
y ==
pueden tener implementaciones personalizadas. La diferencia es que Equals
es un método virtual (instancia), mientras que operator==
es un método estático. Aparte de eso, pueden comportarse exactamente de la misma manera.
De forma predeterminada, tanto Equals
como ==
comprueban la igualdad de referencia para los tipos de referencia y la igualdad de valores para los tipos de valor. Sin embargo, para la string
, ambos están personalizados para verificar la igualdad de valores.
Hay varias cosas sucediendo. En primer lugar, en este ejemplo:
string s1 = "a";
string s2 = "a";
Console.WriteLine(s1 == s2);
Usted afirma que:
Ambos son referencia de objeto diferente.
Eso no es cierto debido a la internación de cuerdas . s1
y s2
son referencias al mismo objeto. La especificación C # garantiza que, desde la sección 2.4.4.5 de la especificación C # 4:
Cuando dos o más literales de cadena que son equivalentes según el operador de igualdad de cadena (§7.10.7) aparecen en el mismo programa, estos literales de cadena se refieren a la misma instancia de cadena.
Por lo tanto, en este caso particular, aún obtendría "verdadero" incluso si imprimiera object.ReferenceEquals(s1, s2)
, o si lo hiciera usar una comparación de identidad de referencia verdadera con ==
:
object s1 = "a";
object s2 = "a";
Console.WriteLine(s1 == s2); // Still prints True due to string literal interning
Sin embargo, incluso si estas eran referencias a objetos separados, ==
se sobrecarga para la string
. La sobrecarga es una decisión en tiempo de compilación : la implementación a utilizar depende de los tipos de tiempo de compilación de los operandos. Así por ejemplo:
string a = new string(''x'', 1);
string b = new string(''x'', 1);
Console.WriteLine(a == b); // Uses string''s implementation, prints True
object c = a;
object d = b;
Console.WriteLine(c == d); // Reference identity comparison, prints False
Compare eso con object.Equals(object)
que es un método virtual. Como sucede, String
sobrecarga este método, pero lo más importante es que lo anula. Entonces si cambiamos nuestro código a:
string a = new string(''x'', 1);
string b = new string(''x'', 1);
Console.WriteLine(a.Equals((object) b));
object c = a;
object d = b;
Console.WriteLine(c.Equals(d));
... entonces, ambas llamadas de método en el código compilado serán simplemente para object.Equals(object)
, pero seguirán imprimiendo True debido al polimorfismo: se usará la implementación en String
.
Así es como se vería una llamada al método sobrecargado :
string a = new string(''x'', 1);
string b = new string(''x'', 1);
Console.WriteLine(a.Equals(b)); // Calls string.Equals(string)