visual strings not found ejemplo comparestring c# string

strings - string.compare c# ejemplo



¿Los operadores string.Equals() y== son realmente iguales? (8)

Esta pregunta ya tiene una respuesta aquí:

¿Son realmente iguales? Hoy, me encontré con este problema. Aquí está el volcado de la ventana inmediata:

?s "Category" ?tvi.Header "Category" ?s == tvi.Header false ?s.Equals(tvi.Header) true ?s == tvi.Header.ToString() true

Entonces, tanto s como tvi.Header contienen "Category", pero == devuelve false y Equals() devuelve true.

s se define como una cadena, tvi.Header es en realidad un TreeViewItem.Header WPF. Entonces, ¿por qué están dando resultados diferentes? Siempre pensé que eran intercambiables en C #.

¿Alguien puede explicar por qué esto es?


Además de la respuesta de Jon Skeet , me gustaría explicar por qué la mayoría de las veces, al usar == , la respuesta es true en diferentes instancias de cadena con el mismo valor:

string a = "Hell"; string b = "Hello"; a = a + "o"; Console.WriteLine(a == b);

Como puede ver, b deben ser instancias de cadena diferentes, pero debido a que las cadenas son inmutables, el tiempo de ejecución utiliza el llamado internado de cadena para permitir que a b referencia a la misma cadena en la memoria. El operador == para objetos verifica la referencia, y dado que tanto a como b referencia a la misma instancia, el resultado es true . Cuando cambias uno de ellos, se crea una nueva instancia de cadena, por lo que la internación de cadena es posible.

Por cierto, la respuesta de Jon Skeet no es completa. De hecho, x == y es false pero eso es solo porque está comparando objetos y los objetos se comparan por referencia. Si escribe (string)x == (string)y , devolverá true nuevamente. Por lo tanto, las cadenas tienen su == - operador sobrecargado, que llama a String.Equals debajo.


Aquí hay muchas respuestas descriptivas, así que no voy a repetir lo que ya se ha dicho. Lo que me gustaría agregar es el siguiente código que muestra todas las permutaciones que se me ocurren. El código es bastante largo debido al número de combinaciones. Siéntase libre de colocarlo en MSTest y ver la salida por sí mismo (la salida se incluye en la parte inferior).

Esta evidencia apoya la respuesta de Jon Skeet.

Código:

[TestMethod] public void StringEqualsMethodVsOperator() { string s1 = new StringBuilder("string").ToString(); string s2 = new StringBuilder("string").ToString(); Debug.WriteLine("string a = /"string/";"); Debug.WriteLine("string b = /"string/";"); TryAllStringComparisons(s1, s2); s1 = null; s2 = null; Debug.WriteLine(string.Join(string.Empty, Enumerable.Repeat("-", 20))); Debug.WriteLine(string.Empty); Debug.WriteLine("string a = null;"); Debug.WriteLine("string b = null;"); TryAllStringComparisons(s1, s2); } private void TryAllStringComparisons(string s1, string s2) { Debug.WriteLine(string.Empty); Debug.WriteLine("-- string.Equals --"); Debug.WriteLine(string.Empty); Try((a, b) => string.Equals(a, b), s1, s2); Try((a, b) => string.Equals((object)a, b), s1, s2); Try((a, b) => string.Equals(a, (object)b), s1, s2); Try((a, b) => string.Equals((object)a, (object)b), s1, s2); Debug.WriteLine(string.Empty); Debug.WriteLine("-- object.Equals --"); Debug.WriteLine(string.Empty); Try((a, b) => object.Equals(a, b), s1, s2); Try((a, b) => object.Equals((object)a, b), s1, s2); Try((a, b) => object.Equals(a, (object)b), s1, s2); Try((a, b) => object.Equals((object)a, (object)b), s1, s2); Debug.WriteLine(string.Empty); Debug.WriteLine("-- a.Equals(b) --"); Debug.WriteLine(string.Empty); Try((a, b) => a.Equals(b), s1, s2); Try((a, b) => a.Equals((object)b), s1, s2); Try((a, b) => ((object)a).Equals(b), s1, s2); Try((a, b) => ((object)a).Equals((object)b), s1, s2); Debug.WriteLine(string.Empty); Debug.WriteLine("-- a == b --"); Debug.WriteLine(string.Empty); Try((a, b) => a == b, s1, s2); #pragma warning disable 252 Try((a, b) => (object)a == b, s1, s2); #pragma warning restore 252 #pragma warning disable 253 Try((a, b) => a == (object)b, s1, s2); #pragma warning restore 253 Try((a, b) => (object)a == (object)b, s1, s2); } public void Try<T1, T2, T3>(Expression<Func<T1, T2, T3>> tryFunc, T1 in1, T2 in2) { T3 out1; Try(tryFunc, e => { }, in1, in2, out out1); } public bool Try<T1, T2, T3>(Expression<Func<T1, T2, T3>> tryFunc, Action<Exception> catchFunc, T1 in1, T2 in2, out T3 out1) { bool success = true; out1 = default(T3); try { out1 = tryFunc.Compile()(in1, in2); Debug.WriteLine("{0}: {1}", tryFunc.Body.ToString(), out1); } catch (Exception ex) { Debug.WriteLine("{0}: {1} - {2}", tryFunc.Body.ToString(), ex.GetType().ToString(), ex.Message); success = false; catchFunc(ex); } return success; }

Salida:

string a = "string"; string b = "string"; -- string.Equals -- Equals(a, b): True Equals(Convert(a), b): True Equals(a, Convert(b)): True Equals(Convert(a), Convert(b)): True -- object.Equals -- Equals(a, b): True Equals(Convert(a), b): True Equals(a, Convert(b)): True Equals(Convert(a), Convert(b)): True -- a.Equals(b) -- a.Equals(b): True a.Equals(Convert(b)): True Convert(a).Equals(b): True Convert(a).Equals(Convert(b)): True -- a == b -- (a == b): True (Convert(a) == b): False (a == Convert(b)): False (Convert(a) == Convert(b)): False -------------------- string a = null; string b = null; -- string.Equals -- Equals(a, b): True Equals(Convert(a), b): True Equals(a, Convert(b)): True Equals(Convert(a), Convert(b)): True -- object.Equals -- Equals(a, b): True Equals(Convert(a), b): True Equals(a, Convert(b)): True Equals(Convert(a), Convert(b)): True -- a.Equals(b) -- a.Equals(b): System.NullReferenceException - Object reference not set to an instance of an object. a.Equals(Convert(b)): System.NullReferenceException - Object reference not set to an instance of an object. Convert(a).Equals(b): System.NullReferenceException - Object reference not set to an instance of an object. Convert(a).Equals(Convert(b)): System.NullReferenceException - Object reference not set to an instance of an object. -- a == b -- (a == b): True (Convert(a) == b): True (a == Convert(b)): True (Convert(a) == Convert(b)): True


C # tiene dos conceptos "iguales": Equals y ReferenceEquals . Para la mayoría de las clases que encontrará, el operador == usa uno u otro (o ambos), y generalmente solo prueba los ReferenceEquals cuando maneja tipos de referencia (pero la clase de string es una instancia donde C # ya sabe cómo probar la igualdad de valores) .

  • Equals compara valores. (Aunque dos variables int separadas no existen en el mismo lugar en la memoria, pueden contener el mismo valor).
  • ReferenceEquals compara la referencia y devuelve si los operandos apuntan al mismo objeto en la memoria.

Código de ejemplo:

var s1 = new StringBuilder("str"); var s2 = new StringBuilder("str"); StringBuilder sNull = null; s1.Equals(s2); // True object.ReferenceEquals(s1, s2); // False s1 == s2 // True - it calls Equals within operator overload s1 == sNull // False object.ReferenceEquals(s1, sNull); // False s1.Equals(sNull); // Nono! Explode (Exception)


Dos diferencias:

  • Equals es polimórfico (es decir, se puede anular y la implementación utilizada dependerá del tipo de tiempo de ejecución del objeto de destino), mientras que la implementación de == used se determina en función de los tipos de tiempo de compilación de los objetos:

    // Avoid getting confused by interning object x = new StringBuilder("hello").ToString(); object y = new StringBuilder("hello").ToString(); if (x.Equals(y)) // Yes // The compiler doesn''t know to call ==(string, string) so it generates // a reference comparision instead if (x == y) // No string xs = (string) x; string ys = (string) y; // Now *this* will call ==(string, string), comparing values appropriately if (xs == ys) // Yes

  • Equals se dispararán si lo llamas nulo, == no lo hará

    string x = null; string y = null; if (x.Equals(y)) // Bang if (x == y) // Yes

Tenga en cuenta que puede evitar que esto último sea un problema al usar object.Equals :

if (object.Equals(x, y)) // Fine even if x or y is null


Está claro que tvi.header no es una String . El == es un operador que está sobrecargado por String clase String , lo que significa que funcionará solo si el compilador sabe que ambos lados del operador son String .


La propiedad Header del TreeViewItem se escribe estáticamente para ser de tipo object .

Por lo tanto, el == produce false . Puede reproducir esto con el siguiente fragmento simple:

object s1 = "Hallo"; // don''t use a string literal to avoid interning string s2 = new string(new char[] { ''H'', ''a'', ''l'', ''l'', ''o'' }); bool equals = s1 == s2; // equals is false equals = string.Equals(s1, s2); // equals is true


Las contradicciones aparentes que aparecen en la pregunta se deben a que en un caso se llama a la función Equals en un objeto de string y en el otro caso al operador == se llama en el tipo System.Object . string y el object implementan la igualdad de manera diferente entre sí (valor frente a referencia, respectivamente).

Más allá de este hecho, cualquier tipo puede definir == y es Equals diferente, por lo que en general no son intercambiables.

Aquí hay un ejemplo que usa double (de la nota de Joseph Albahari a §7.9.2 de la especificación del lenguaje C #):

double x = double.NaN; Console.WriteLine (x == x); // False Console.WriteLine (x != x); // True Console.WriteLine (x.Equals(x)); // True

Continúa diciendo que el double.Equals(double) fue diseñado para funcionar correctamente con listas y diccionarios. El operador == , por otro lado, fue diseñado para seguir el estándar IEEE 754 para los tipos de punto flotante.

En el caso específico de determinar la igualdad de cadenas, la preferencia de la industria es no utilizar == ni string.Equals(string) mayor parte del tiempo. Estos métodos determinan si dos cadenas son del mismo carácter por carácter, que rara vez es el comportamiento correcto. Es mejor usar string.Equals(string, StringComparison) , que le permite especificar un tipo particular de comparación. Al utilizar la comparación correcta, puede evitar muchos errores potenciales (muy difíciles de diagnosticar).

Aquí hay un ejemplo:

string one = "Caf/u00e9"; // U+00E9 LATIN SMALL LETTER E WITH ACUTE string two = "Cafe/u0301"; // U+0301 COMBINING ACUTE ACCENT Console.WriteLine(one == two); // False Console.WriteLine(one.Equals(two)); // False Console.WriteLine(one.Equals(two, StringComparison.InvariantCulture)); // True

Ambas cadenas en este ejemplo tienen el mismo aspecto ("Café"), por lo que esto podría ser muy difícil de depurar si se utiliza una igualdad ingenua (ordinal).


Un objeto está definido por un OBJECT_ID, que es único. Si A y B son objetos y A == B es verdadero, entonces son el mismo objeto, tienen los mismos datos y métodos, pero esto también es cierto:

A.OBJECT_ID == B.OBJECT_ID

si A.Equals (B) es verdadero, eso significa que los dos objetos están en el mismo estado, pero esto no significa que A sea lo mismo que B.

Las cuerdas son objetos.

Tenga en cuenta que los operadores == y Igual son reflexivos, simétricos, tranzitivos, por lo que son relaciones equivalénicas (para usar términos algebraicos relacionales)

Lo que esto significa: si A, B y C son objetos, entonces:

(1) A == A es siempre verdadera; A. Las ecuaciones (A) siempre son ciertas (reflexividad)

(2) si A == B entonces B == A; Si A.Equals (B) entonces B.Equals (A) (simetría)

(3) si A == B y B == C, entonces A == C; si A.Equals (B) y B.Equals (C) entonces A.Equals (C) (tranzitividad)

Además, puedes notar que esto también es cierto:

(A == B) => (A.Equals (B)), pero lo inverso no es cierto.

A B => 0 0 1 0 1 1 1 0 0 1 1 1

Ejemplo de la vida real: dos hamburguesas del mismo tipo tienen las mismas propiedades: son objetos de la clase Hamburger, sus propiedades son exactamente iguales, pero son entidades diferentes. Si compras estas dos hamburguesas y comes una, la otra no se comerá. Entonces, la diferencia entre Igual y ==: Tienes hamburguesa1 y hamburguesa2. Están exactamente en el mismo estado (el mismo peso, la misma temperatura, el mismo sabor), por lo que hamburger1.Equals (hamburger2) es cierto. Pero hamburger1 == hamburger2 es falso, porque si el estado de hamburger1 cambia, el estado de hamburger2 no necesariamente cambia y viceversa.

Si usted y un amigo obtienen una hamburguesa, que es la suya y la suya al mismo tiempo, entonces debe decidir dividir la hamburguesa en dos partes, porque usted.getHamburger () == friend.getHamburger () es verdad y si esto sucede : friend.eatHamburger (), entonces tu Hamburguesa también se comerá.

Podría escribir otros matices sobre Equals y ==, pero tengo hambre, así que tengo que irme.

Saludos cordiales, Lajos Arpad.