Cómo: Comparar cadenas (Guía de programación de C#)
Cuando se comparan cadenas, se genera un resultado que indica que una cadena es mayor o menor que otra o que las dos cadenas son iguales. Las reglas por las que se determina el resultado son distintas dependiendo de que se realice una comparación ordinal o una comparación dependiente de la referencia cultural. Es importante utilizar el tipo correcto de comparación para cada tarea concreta.
Utilice comparaciones ordinales básicas cuando tenga que comparar u ordenar los valores de dos cadenas sin tener en cuenta las convenciones lingüísticas. Una comparación ordinal básica (System.StringComparison.Ordinal) distingue entre mayúsculas y minúsculas, lo que significa que las dos cadenas deben coincidir carácter por carácter: "and" no es igual que "And" o "AND". Una variación utilizada con frecuencia es System.StringComparison.OrdinalIgnoreCase, que coincidirá con "and" "And" y "AND". StringComparison.OrdinalIgnoreCase se suele usar para comparar nombres de archivo, nombres de ruta de acceso, rutas de red y cualquier otra cadena cuyo valor no cambie en función de la configuración regional del equipo del usuario. Para obtener más información, vea StringComparison.
Las comparaciones dependientes de la referencia cultural se utilizan normalmente para comparar y ordenar cadenas especificadas por usuarios finales, ya que los caracteres y las convenciones de ordenación de estas cadenas pueden variar dependiendo de la configuración regional del equipo del usuario. Incluso las cadenas que contienen caracteres idénticos pueden ordenarse de forma distinta dependiendo de la referencia cultural del subproceso actual.
Nota |
---|
Al comparar cadenas, debe utilizar los métodos que especifican explícitamente el tipo de comparación que desea realizar.Esto hace que su código sea mucho más fácil de mantener y leer.Siempre que sea posible, utilice las sobrecargas de los métodos de las clases String y Array que toman un parámetro de enumeración StringComparison, de forma que pueda especificar qué tipo de comparación se va a realizar.Es conveniente evitar el uso de los operadores == y != al comparar cadenas.Asimismo, evite utilizar los métodos de instancia String.CompareTo, ya que ninguna de las sobrecargas toma un elemento StringComparison. |
Ejemplo
En el ejemplo siguiente se muestra cómo comparar correctamente las cadenas cuyos valores no cambiarán en función de la configuración regional del equipo del usuario. Además, también muestra la característica asignación al grupo interno de cadenas de C#. Cuando un programa declara dos o más variables de cadena idénticas, el compilador las almacena en la misma ubicación. Al llamar al método ReferenceEquals, puede ver que las dos cadenas hacen referencia realmente al mismo objeto en memoria. Utilice el método String.Copy para evitar el proceso de asignación al grupo interno de cadenas, como se muestra en el ejemplo.
// Internal strings that will never be localized.
string root = @"C:\users";
string root2 = @"C:\Users";
// Use the overload of the Equals method that specifies a StringComparison.
// Ordinal is the fastest way to compare two strings.
bool result = root.Equals(root2, StringComparison.Ordinal);
Console.WriteLine("Ordinal comparison: {0} and {1} are {2}", root, root2,
result ? "equal." : "not equal.");
// To ignore case means "user" equals "User". This is the same as using
// String.ToUpperInvariant on each string and then performing an ordinal comparison.
result = root.Equals(root2, StringComparison.OrdinalIgnoreCase);
Console.WriteLine("Ordinal ignore case: {0} and {1} are {2}", root, root2,
result ? "equal." : "not equal.");
// A static method is also available.
bool areEqual = String.Equals(root, root2, StringComparison.Ordinal);
// String interning. Are these really two distinct objects?
string a = "The computer ate my source code.";
string b = "The computer ate my source code.";
// ReferenceEquals returns true if both objects
// point to the same location in memory.
if (String.ReferenceEquals(a, b))
Console.WriteLine("a and b are interned.");
else
Console.WriteLine("a and b are not interned.");
// Use String.Copy method to avoid interning.
string c = String.Copy(a);
if (String.ReferenceEquals(a, c))
Console.WriteLine("a and c are interned.");
else
Console.WriteLine("a and c are not interned.");
// Output:
// Ordinal comparison: C:\users and C:\Users are not equal.
// Ordinal ignore case: C:\users and C:\Users are equal.
// a and b are interned.
// a and c are not interned.
En el ejemplo siguiente se muestra cómo comparar cadenas de la mejor forma utilizando los métodos String que toman una enumeración StringComparison. Tenga en cuenta que aquí no se utilizan los métodos de instanciaString.CompareTo, ya que ninguna de las sobrecargas toma un elemento StringComparison.
// "They dance in the street."
// Linguistically (in Windows), "ss" is equal to
// the German essetz: 'ß' character in both en-US and de-DE cultures.
string first = "Sie tanzen in die Straße.";
string second = "Sie tanzen in die Strasse.";
Console.WriteLine("First sentence is {0}", first);
Console.WriteLine("Second sentence is {0}", second);
// Store CultureInfo for the current culture. Note that the original culture
// can be set and retrieved on the current thread object.
System.Threading.Thread thread = System.Threading.Thread.CurrentThread;
System.Globalization.CultureInfo originalCulture = thread.CurrentCulture;
// Set the culture to en-US.
thread.CurrentCulture = new System.Globalization.CultureInfo("en-US");
// For culture-sensitive comparisons, use the String.Compare
// overload that takes a StringComparison value.
int i = String.Compare(first, second, StringComparison.CurrentCulture);
Console.WriteLine("Comparing in {0} returns {1}.", originalCulture.Name, i);
// Change the current culture to Deutch-Deutchland.
thread.CurrentCulture = new System.Globalization.CultureInfo("de-DE");
i = String.Compare(first, second, StringComparison.CurrentCulture);
Console.WriteLine("Comparing in {0} returns {1}.", thread.CurrentCulture.Name, i);
// For culture-sensitive string equality, use either StringCompare as above
// or the String.Equals overload that takes a StringComparison value.
thread.CurrentCulture = originalCulture;
bool b = String.Equals(first, second, StringComparison.CurrentCulture);
Console.WriteLine("The two strings {0} equal.", b == true ? "are" : "are not");
/*
* Output:
First sentence is Sie tanzen in die Straße.
Second sentence is Sie tanzen in die Strasse.
Comparing in en-US returns 0.
Comparing in de-DE returns 0.
The two strings are equal.
*/
En el ejemplo siguiente se muestra cómo ordenar y buscar cadenas en una matriz de forma que se tenga en cuenta la referencia cultural mediante los métodos estáticos Array que toman un parámetro StringComparer.
class SortStringArrays
{
static void Main()
{
string[] lines = new string[]
{
@"c:\public\textfile.txt",
@"c:\public\textFile.TXT",
@"c:\public\Text.txt",
@"c:\public\testfile2.txt"
};
Console.WriteLine("Non-sorted order:");
foreach (string s in lines)
{
Console.WriteLine(" {0}", s);
}
Console.WriteLine("\n\rSorted order:");
// Specify Ordinal to demonstrate the different behavior.
Array.Sort(lines, StringComparer.Ordinal);
foreach (string s in lines)
{
Console.WriteLine(" {0}", s);
}
string searchString = @"c:\public\TEXTFILE.TXT";
Console.WriteLine("Binary search for {0}", searchString);
int result = Array.BinarySearch(lines, searchString, StringComparer.OrdinalIgnoreCase);
ShowWhere<string>(lines, result);
//Console.WriteLine("{0} {1}", result > 0 ? "Found" : "Did not find", searchString);
// Keep the console window open in debug mode.
System.Console.WriteLine("Press any key to exit.");
System.Console.ReadKey();
}
// Displays where the string was found, or, if not found,
// where it would have been located.
private static void ShowWhere<T>(T[] array, int index)
{
if (index < 0)
{
// If the index is negative, it represents the bitwise
// complement of the next larger element in the array.
index = ~index;
Console.Write("Not found. Sorts between: ");
if (index == 0)
Console.Write("beginning of array and ");
else
Console.Write("{0} and ", array[index - 1]);
if (index == array.Length)
Console.WriteLine("end of array.");
else
Console.WriteLine("{0}.", array[index]);
}
else
{
Console.WriteLine("Found at index {0}.", index);
}
}
}
/*
* Output:
Non-sorted order:
c:\public\textfile.txt
c:\public\textFile.TXT
c:\public\Text.txt
c:\public\testfile2.txt
Sorted order:
c:\public\Text.txt
c:\public\testfile2.txt
c:\public\textFile.TXT
c:\public\textfile.txt
Binary search for c:\public\TEXTFILE.TXT
Found at index 2.
*/
Las clases de colección como Hashtable, Dictionary y List tienen constructores que toman un parámetro StringComparer cuando el tipo de los elementos o las claves es string. En general, debe usar estos constructores siempre que sea posible y especificar Ordinal u OrdinalIgnoreCase.
Vea también
Referencia
Conceptos
Comparar cadenas en .NET Framework