Clase System.String

En este artículo se proporcionan comentarios adicionales a la documentación de referencia de esta API.

Una cadena es una colección secuencial de caracteres que se usa para representar texto. Un String objeto es una colección secuencial de System.Char objetos que representan una cadena; un System.Char objeto corresponde a una unidad de código UTF-16. El valor del String objeto es el contenido de la colección secuencial de System.Char objetos y ese valor es inmutable (es decir, es de sólo lectura). Para obtener más información sobre la inmutabilidad de las cadenas, consulte la sección Inmutabilidad y la clase StringBuilder. El tamaño máximo de un String objeto en memoria es de 2 GB o aproximadamente 1000 millones de caracteres.

Para obtener más información sobre Unicode, UTF-16, unidades de código, puntos de código y tipos CharRune , vea Introducción a la codificación de caracteres en .NET.

Creación de una instancia de un objeto String

Puede crear instancias de un String objeto de las maneras siguientes:

  • Mediante la asignación de un literal de cadena a una String variable. Este es el método más usado para crear una cadena. En el ejemplo siguiente se usa la asignación para crear varias cadenas. Tenga en cuenta que en C# y F#, dado que la barra diagonal inversa (\) es un carácter de escape, las barras diagonales inversas literales de una cadena deben tener un escape o toda la cadena debe ser @-quoted.

    string string1 = "This is a string created by assignment.";
    Console.WriteLine(string1);
    string string2a = "The path is C:\\PublicDocuments\\Report1.doc";
    Console.WriteLine(string2a);
    string string2b = @"The path is C:\PublicDocuments\Report1.doc";
    Console.WriteLine(string2b);
    // The example displays the following output:
    //       This is a string created by assignment.
    //       The path is C:\PublicDocuments\Report1.doc
    //       The path is C:\PublicDocuments\Report1.doc
    
    let string1 = "This is a string created by assignment."
    printfn "%s" string1
    let string2a = "The path is C:\\PublicDocuments\\Report1.doc"
    printfn "%s" string2a
    let string2b = @"The path is C:\PublicDocuments\Report1.doc"
    printfn "%s" string2b
    // The example displays the following output:
    //       This is a string created by assignment.
    //       The path is C:\PublicDocuments\Report1.doc
    //       The path is C:\PublicDocuments\Report1.doc
    
    Dim string1 As String = "This is a string created by assignment."
    Console.WriteLine(string1)
    Dim string2 As String = "The path is C:\PublicDocuments\Report1.doc"
    Console.WriteLine(string2)
    ' The example displays the following output:
    '       This is a string created by assignment.
    '       The path is C:\PublicDocuments\Report1.doc
    
  • Mediante una llamada a un String constructor de clase. En el ejemplo siguiente se crean instancias de cadenas mediante una llamada a varios constructores de clase. Tenga en cuenta que algunos de los constructores incluyen punteros a matrices de caracteres o matrices de bytes firmadas como parámetros. Visual Basic no admite llamadas a estos constructores. Para obtener información detallada sobre String los constructores, consulte el resumen del String constructor.

    char[] chars = { 'w', 'o', 'r', 'd' };
    sbyte[] bytes = { 0x41, 0x42, 0x43, 0x44, 0x45, 0x00 };
    
    // Create a string from a character array.
    string string1 = new string(chars);
    Console.WriteLine(string1);
    
    // Create a string that consists of a character repeated 20 times.
    string string2 = new string('c', 20);
    Console.WriteLine(string2);
    
    string stringFromBytes = null;
    string stringFromChars = null;
    unsafe
    {
       fixed (sbyte* pbytes = bytes)
       {
          // Create a string from a pointer to a signed byte array.
          stringFromBytes = new string(pbytes);
       }
       fixed (char* pchars = chars)
       {
          // Create a string from a pointer to a character array.
          stringFromChars = new string(pchars);
       }
    }
    Console.WriteLine(stringFromBytes);
    Console.WriteLine(stringFromChars);
    // The example displays the following output:
    //       word
    //       cccccccccccccccccccc
    //       ABCDE
    //       word
    
    let chars = [| 'w'; 'o'; 'r'; 'd' |]
    let bytes = [| 0x41y; 0x42y; 0x43y; 0x44y; 0x45y; 0x00y |]
    
    // Create a string from a character array.
    let string1 = String chars
    printfn "%s" string1
    
    // Create a string that consists of a character repeated 20 times.
    let string2 = String('c', 20)
    printfn "%s" string2
    
    let stringFromBytes =
        // Create a string from a pointer to a signed byte array.
        use pbytes = fixed bytes
        String pbytes
    let stringFromChars = 
        // Create a string from a pointer to a character array.
        use pchars = fixed chars
        String pchars
    
    printfn $"{stringFromBytes}"
    printfn $"{stringFromChars}"
    // The example displays the following output:
    //       word
    //       cccccccccccccccccccc
    //       ABCDE
    //       word
    
    Dim chars() As Char = {"w"c, "o"c, "r"c, "d"c}
    
    ' Create a string from a character array.
    Dim string1 As New String(chars)
    Console.WriteLine(string1)
    
    ' Create a string that consists of a character repeated 20 times.
    Dim string2 As New String("c"c, 20)
    Console.WriteLine(string2)
    ' The example displays the following output:
    '       word
    '       cccccccccccccccccccc
    
  • Mediante el uso del operador de concatenación de cadenas (+ en C# y F#, y & o + en Visual Basic) para crear una sola cadena a partir de cualquier combinación de instancias y literales de String cadena. En el ejemplo siguiente se muestra el uso del operador de concatenación de cadenas.

    string string1 = "Today is " + DateTime.Now.ToString("D") + ".";
    Console.WriteLine(string1);
    
    string string2 = "This is one sentence. " + "This is a second. ";
    string2 += "This is a third sentence.";
    Console.WriteLine(string2);
    // The example displays output like the following:
    //    Today is Tuesday, July 06, 2011.
    //    This is one sentence. This is a second. This is a third sentence.
    
    let string1 = "Today is " + DateTime.Now.ToString("D") + "."
    printfn $"{string1}"
    
    let string2 = "This is one sentence. " + "This is a second. "
    let string2 = string2 + "This is a third sentence."
    printfn $"{string2}"
    // The example displays output like the following:
    //    Today is Tuesday, July 06, 2011.
    //    This is one sentence. This is a second. This is a third sentence.
    
    Dim string1 As String = "Today is " + Date.Now.ToString("D") + "."
    Console.WriteLine(string1)
    Dim string2 As String = "This is one sentence. " + "This is a second. "
    string2 += "This is a third sentence."
    Console.WriteLine(string2)
    ' The example displays output like the following:
    '    Today is Tuesday, July 06, 2011.
    '    This is one sentence. This is a second. This is a third sentence.
    
  • Al recuperar una propiedad o llamar a un método que devuelve una cadena. En el ejemplo siguiente se usan los métodos de la String clase para extraer una subcadena de una cadena mayor.

    string sentence = "This sentence has five words.";
    // Extract the second word.
    int startPosition = sentence.IndexOf(" ") + 1;
    string word2 = sentence.Substring(startPosition,
                                      sentence.IndexOf(" ", startPosition) - startPosition);
    Console.WriteLine("Second word: " + word2);
    // The example displays the following output:
    //       Second word: sentence
    
    let sentence = "This sentence has five words."
    // Extract the second word.
    let startPosition = sentence.IndexOf " " + 1
    let word2 = 
        sentence.Substring(startPosition, sentence.IndexOf(" ", startPosition) - startPosition)
    printfn $"Second word: {word2}"
    // The example displays the following output:
    //       Second word: sentence
    
    Dim sentence As String = "This sentence has five words."
    ' Extract the second word.
    Dim startPosition As Integer = sentence.IndexOf(" ") + 1
    Dim word2 As String = sentence.Substring(startPosition,
                                           sentence.IndexOf(" ", startPosition) - startPosition)
    Console.WriteLine("Second word: " + word2)
    ' The example displays the following output:
    '       Second word: sentence
    
  • Llamando a un método de formato para convertir un valor o objeto en su representación de cadena. En el ejemplo siguiente se usa la característica de formato compuesto para insertar la representación de cadena de dos objetos en una cadena.

    DateTime dateAndTime = new DateTime(2011, 7, 6, 7, 32, 0);
    double temperature = 68.3;
    string result = String.Format("At {0:t} on {0:D}, the temperature was {1:F1} degrees Fahrenheit.",
                                  dateAndTime, temperature);
    Console.WriteLine(result);
    // The example displays the following output:
    //       At 7:32 AM on Wednesday, July 06, 2011, the temperature was 68.3 degrees Fahrenheit.
    
    let dateAndTime = DateTime(2011, 7, 6, 7, 32, 0)
    let temperature = 68.3
    String.Format("At {0:t} on {0:D}, the temperature was {1:F1} degrees Fahrenheit.", dateAndTime, temperature)
    |> printfn "%s"
    // The example displays the following output:
    //       At 7:32 AM on Wednesday, July 06, 2011, the temperature was 68.3 degrees Fahrenheit.
    
    Dim dateAndTime As DateTime = #07/06/2011 7:32:00AM#
    Dim temperature As Double = 68.3
    Dim result As String = String.Format("At {0:t} on {0:D}, the temperature was {1:F1} degrees Fahrenheit.",
                                       dateAndTime, temperature)
    Console.WriteLine(result)
    ' The example displays the following output:
    '       At 7:32 AM on Wednesday, July 06, 2011, the temperature was 68.3 degrees Fahrenheit.
    

Objetos Char y caracteres Unicode

Cada carácter de una cadena se define mediante un valor escalar Unicode, también denominado punto de código Unicode o el valor ordinal (numérico) del carácter Unicode. Cada punto de código se codifica mediante codificación UTF-16 y el valor numérico de cada elemento de la codificación se representa mediante un Char objeto .

Nota:

Tenga en cuenta que, dado que una String instancia consta de una colección secuencial de unidades de código UTF-16, es posible crear un String objeto que no sea una cadena Unicode bien formada. Por ejemplo, es posible crear una cadena que tenga un suplente bajo sin un suplente alto correspondiente. Aunque algunos métodos, como los métodos de codificación y descodificación de objetos en el System.Text espacio de nombres, pueden realizar comprobaciones para asegurarse de que las cadenas tienen un formato correcto, String los miembros de clase no garantizan que una cadena tenga un formato correcto.

Normalmente, un único Char objeto representa un único punto de código; es decir, el valor numérico de es igual al punto de Char código. Por ejemplo, el punto de código del carácter "a" es U+0061. Sin embargo, un punto de código podría requerir más de un elemento codificado (más de un Char objeto). El estándar Unicode define dos tipos de caracteres que corresponden a varios Char objetos: grafos y puntos de código complementarios Unicode que corresponden a caracteres en los planos complementarios Unicode.

  • Un grafo se representa mediante un carácter base seguido de uno o varios caracteres combinados. Por ejemplo, el carácter ä se representa mediante un Char objeto cuyo punto de código es U+0061 seguido de un Char objeto cuyo punto de código es U+0308. Este carácter también se puede definir mediante un único Char objeto que tiene un punto de código de U+00E4. Como se muestra en el ejemplo siguiente, una comparación que distingue referencias culturales para la igualdad indica que estas dos representaciones son iguales, aunque no lo hace una comparación ordinal normal. Sin embargo, si se normalizan las dos cadenas, una comparación ordinal también indica que son iguales. (Para obtener más información sobre la normalización de cadenas, consulte Sección de normalización ).

    using System;
    using System.Globalization;
    using System.IO;
    
    public class Example5
    {
       public static void Main()
       {
          StreamWriter sw = new StreamWriter(@".\graphemes.txt");
          string grapheme = "\u0061\u0308";
          sw.WriteLine(grapheme);
          
          string singleChar = "\u00e4";
          sw.WriteLine(singleChar);
                
          sw.WriteLine("{0} = {1} (Culture-sensitive): {2}", grapheme, singleChar, 
                       String.Equals(grapheme, singleChar, 
                                     StringComparison.CurrentCulture));
          sw.WriteLine("{0} = {1} (Ordinal): {2}", grapheme, singleChar, 
                       String.Equals(grapheme, singleChar, 
                                     StringComparison.Ordinal));
          sw.WriteLine("{0} = {1} (Normalized Ordinal): {2}", grapheme, singleChar, 
                       String.Equals(grapheme.Normalize(), 
                                     singleChar.Normalize(), 
                                     StringComparison.Ordinal));
          sw.Close(); 
       }
    }
    // The example produces the following output:
    //       ä
    //       ä
    //       ä = ä (Culture-sensitive): True
    //       ä = ä (Ordinal): False
    //       ä = ä (Normalized Ordinal): True
    
    open System
    open System.IO
    
    do
        use sw = new StreamWriter(@".\graphemes.txt")
        let grapheme = "\u0061\u0308"
        sw.WriteLine grapheme
    
        let singleChar = "\u00e4"
        sw.WriteLine singleChar
    
        sw.WriteLine("{0} = {1} (Culture-sensitive): {2}", grapheme, singleChar, 
                    String.Equals(grapheme, singleChar,
                                    StringComparison.CurrentCulture))
        sw.WriteLine("{0} = {1} (Ordinal): {2}", grapheme, singleChar,
                    String.Equals(grapheme, singleChar,
                                    StringComparison.Ordinal))
        sw.WriteLine("{0} = {1} (Normalized Ordinal): {2}", grapheme, singleChar,
                    String.Equals(grapheme.Normalize(),
                                    singleChar.Normalize(),
                                    StringComparison.Ordinal))
    // The example produces the following output:
    //       ä
    //       ä
    //       ä = ä (Culture-sensitive): True
    //       ä = ä (Ordinal): False
    //       ä = ä (Normalized Ordinal): True
    
    Imports System.Globalization
    Imports System.IO
    
    Module Example9
        Public Sub Main()
            Dim sw As New StreamWriter(".\graphemes.txt")
            Dim grapheme As String = ChrW(&H61) + ChrW(&H308)
            sw.WriteLine(grapheme)
    
            Dim singleChar As String = ChrW(&HE4)
            sw.WriteLine(singleChar)
    
            sw.WriteLine("{0} = {1} (Culture-sensitive): {2}", grapheme, singleChar,
                       String.Equals(grapheme, singleChar,
                                     StringComparison.CurrentCulture))
            sw.WriteLine("{0} = {1} (Ordinal): {2}", grapheme, singleChar,
                       String.Equals(grapheme, singleChar,
                                     StringComparison.Ordinal))
            sw.WriteLine("{0} = {1} (Normalized Ordinal): {2}", grapheme, singleChar,
                       String.Equals(grapheme.Normalize(),
                                     singleChar.Normalize(),
                                     StringComparison.Ordinal))
            sw.Close()
        End Sub
    End Module
    ' The example produces the following output:
    '       ä
    '       ä
    '       ä = ä (Culture-sensitive): True
    '       ä = ä (Ordinal): False
    '       ä = ä (Normalized Ordinal): True
    
  • Un punto de código complementario Unicode (un par suplente) se representa mediante un Char objeto cuyo punto de código es un suplente alto seguido de un Char objeto cuyo punto de código es un suplente bajo. Las unidades de código de los suplentes altos oscilan entre U+D800 y U+DBFF. Las unidades de código de los suplentes bajos oscilan entre U+DC00 y U+DFFF. Los pares suplentes se usan para representar caracteres en los planos complementarios Unicode 16. En el ejemplo siguiente se crea un carácter suplente y se pasa al Char.IsSurrogatePair(Char, Char) método para determinar si es un par suplente.

    string surrogate = "\uD800\uDC03";
    for (int ctr = 0; ctr < surrogate.Length; ctr++) 
       Console.Write($"U+{(ushort)surrogate[ctr]:X2} ");
    
    Console.WriteLine();
    Console.WriteLine("   Is Surrogate Pair: {0}", 
                      Char.IsSurrogatePair(surrogate[0], surrogate[1]));
    // The example displays the following output:
    //       U+D800 U+DC03
    //          Is Surrogate Pair: True
    
    open System
    
    let surrogate = "\uD800\uDC03"
    for i = 0 to surrogate.Length - 1 do
        printf $"U+{uint16 surrogate[i]:X2} "
    
    printfn $"\n   Is Surrogate Pair: {Char.IsSurrogatePair(surrogate[0], surrogate[1])}"
    // The example displays the following output:
    //       U+D800 U+DC03
    //          Is Surrogate Pair: True
    
    Module Example20
        Public Sub Main()
            Dim surrogate As String = ChrW(&HD800) + ChrW(&HDC03)
            For ctr As Integer = 0 To surrogate.Length - 1
                Console.Write("U+{0:X2} ", Convert.ToUInt16(surrogate(ctr)))
            Next
            Console.WriteLine()
            Console.WriteLine("   Is Surrogate Pair: {0}",
                            Char.IsSurrogatePair(surrogate(0), surrogate(1)))
        End Sub
    End Module
    
    ' The example displays the following output:
    '       U+D800 U+DC03
    '          Is Surrogate Pair: True
    

Estándar Unicode

Los caracteres de una cadena se representan mediante unidades de código codificadas UTF-16, que corresponden a Char valores.

Cada carácter de una cadena tiene una categoría de caracteres Unicode asociada, que se representa en .NET mediante la UnicodeCategory enumeración. La categoría de un carácter o un par suplente se puede determinar llamando al CharUnicodeInfo.GetUnicodeCategory método .

.NET dispone de una tabla propia de caracteres y de sus categorías correspondientes, cosa que permite garantizar que una versión específica de una implementación de .NET ejecutada en distintas plataformas devuelve la misma información sobre las categorías de caracteres. En todas las versiones de .NET y en todas las plataformas del sistema operativo, la base de datos de caracteres Unicode proporciona información de categoría de caracteres.

En la tabla siguiente se enumeran las versiones de .NET y del estándar Unicode en las que se basan sus categorías de caracteres.

Versión de .NET Versión del estándar Unicode
.NET Framework 1.1 Estándar Unicode, versión 4.0.0
.NET Framework 2.0 Estándar Unicode, versión 5.0.0
.NET Framework 3,5 Estándar Unicode, versión 5.0.0
.NET Framework 4 Estándar Unicode, versión 5.0.0
.NET Framework 4.5 Estándar Unicode, versión 6.3.0
.NET Framework 4.5.1 Estándar Unicode, versión 6.3.0
.NET Framework 4.5.2 Estándar Unicode, versión 6.3.0
.NET Framework 4.6 Estándar Unicode, versión 6.3.0
.NET Framework 4.6.1 Estándar Unicode, versión 6.3.0
.NET Framework 4.6.2 y versiones posteriores Estándar Unicode, versión 8.0.0
.NET Core 2.1 Estándar Unicode, versión 8.0.0
.NET Core 3.1 Estándar Unicode, versión 11.0.0
.NET 5 Estándar Unicode, versión 13.0.0

Además, .NET admite la comparación y ordenación de cadenas en función del estándar Unicode. A partir de .NET Framework 4.5 que se ejecuta en Windows 8 y versiones posteriores del sistema operativo Windows, el entorno de ejecución delega las operaciones de comparación y ordenación de cadenas en el sistema operativo. En .NET Core y .NET 5+, los componentes internacionales proporcionan información de comparación y ordenación de cadenas para bibliotecas Unicode (excepto en versiones de Windows anteriores a Actualización de mayo de 2019 de Windows 10). En la tabla siguiente se enumeran las versiones de .NET y las versiones de Unicode Standard en las que se basan la comparación y ordenación de caracteres.

Versión de .NET Versión del estándar Unicode
.NET Framework 4.5 y versiones posteriores en Windows 7 Estándar Unicode, versión 5.0.0
.NET Framework 4.5 y versiones posteriores en sistemas operativos Windows 8 y versiones posteriores Estándar Unicode, versión 6.3.0
.NET Core, y .NET 5 y versiones posteriores Depende de la versión del estándar Unicode compatible con el sistema operativo subyacente.

Caracteres NULL incrustados

En .NET, un String objeto puede incluir caracteres NULL incrustados, que cuentan como parte de la longitud de la cadena. Sin embargo, en algunos lenguajes como C y C++, un carácter NULL indica el final de una cadena; no se considera una parte de la cadena y no se cuenta como parte de la longitud de la cadena. Esto significa que las siguientes suposiciones comunes de que los programadores o bibliotecas de C y C++ escritos en C o C++ podrían hacer sobre cadenas no son necesariamente válidos cuando se aplican a String objetos:

  • El valor devuelto por las strlen funciones o wcslen no es necesariamente igual a String.Length.

  • La cadena creada por las strcpy_s funciones o wcscpy_s no es necesariamente idéntica a la cadena creada por el String.Copy método .

Debe asegurarse de que el código nativo de C y C++ que crea instancias de String objetos y el código que se pasa String a través de la invocación de plataforma, no suponga que un carácter NULL incrustado marca el final de la cadena.

Los caracteres NULL incrustados en una cadena también se tratan de forma diferente cuando se ordena (o compara) una cadena y cuando se busca una cadena. Los caracteres NULL se omiten al realizar comparaciones que distinguen referencias culturales entre dos cadenas, incluidas las comparaciones que usan la referencia cultural invariable. Se consideran solo para comparaciones ordinales o sin distinción entre mayúsculas y minúsculas. Por otro lado, los caracteres null incrustados siempre se tienen en cuenta al buscar una cadena con métodos como Contains, StartsWithy IndexOf.

Cadenas e índices

Un índice es la posición de un Char objeto (no un carácter Unicode) en un String. Un índice es un número no negativo basado en cero que comienza desde la primera posición de la cadena, que es la posición de índice cero. Varios métodos de búsqueda, como IndexOf y LastIndexOf, devuelven el índice de un carácter o subcadena en la instancia de cadena.

La Chars[] propiedad permite acceder a objetos individuales Char por su posición de índice en la cadena. Dado que la Chars[] propiedad es la propiedad predeterminada (en Visual Basic) o el indexador (en C# y F#), puede tener acceso a los objetos individuales Char de una cadena mediante código como el siguiente. Este código busca espacios en blanco o caracteres de puntuación en una cadena para determinar cuántas palabras contiene la cadena.

string s1 = "This string consists of a single short sentence.";
int nWords = 0;

s1 = s1.Trim();      
for (int ctr = 0; ctr < s1.Length; ctr++) {
   if (Char.IsPunctuation(s1[ctr]) | Char.IsWhiteSpace(s1[ctr]))
      nWords++;              
}
Console.WriteLine("The sentence\n   {0}\nhas {1} words.",
                  s1, nWords);                                                                     
// The example displays the following output:
//       The sentence
//          This string consists of a single short sentence.
//       has 8 words.
let s1 = "This string consists of a single short sentence."
let mutable nWords = 0

for i = 0 to s1.Length - 1 do
    if Char.IsPunctuation s1[i] || Char.IsWhiteSpace s1[i] then
        nWords <- nWords + 1
printfn $"The sentence\n   {s1}\nhas {nWords} words."
// The example displays the following output:
//       The sentence
//          This string consists of a single short sentence.
//       has 8 words.
Module Example12
    Public Sub Main()
        Dim s1 As String = "This string consists of a single short sentence."
        Dim nWords As Integer = 0

        s1 = s1.Trim()
        For ctr As Integer = 0 To s1.Length - 1
            If Char.IsPunctuation(s1(ctr)) Or Char.IsWhiteSpace(s1(ctr)) Then
                nWords += 1
            End If
        Next
        Console.WriteLine("The sentence{2}   {0}{2}has {1} words.",
                        s1, nWords, vbCrLf)
    End Sub
End Module
' The example displays the following output:
'       The sentence
'          This string consists of a single short sentence.
'       has 8 words.

Dado que la String clase implementa la IEnumerable interfaz, también puede recorrer en iteración los Char objetos de una cadena mediante una foreach construcción, como se muestra en el ejemplo siguiente.

string s1 = "This string consists of a single short sentence.";
int nWords = 0;

s1 = s1.Trim();      
foreach (var ch in s1) {
   if (Char.IsPunctuation(ch) | Char.IsWhiteSpace(ch))
      nWords++;              
}
Console.WriteLine("The sentence\n   {0}\nhas {1} words.",
                  s1, nWords);                                                                     
// The example displays the following output:
//       The sentence
//          This string consists of a single short sentence.
//       has 8 words.
let s1 = "This string consists of a single short sentence."
let mutable nWords = 0

for ch in s1 do
    if Char.IsPunctuation ch || Char.IsWhiteSpace ch then
        nWords <- nWords + 1
printfn $"The sentence\n   {s1}\nhas {nWords} words."
// The example displays the following output:
//       The sentence
//          This string consists of a single short sentence.
//       has 8 words.
Module Example13
    Public Sub Main()
        Dim s1 As String = "This string consists of a single short sentence."
        Dim nWords As Integer = 0

        s1 = s1.Trim()
        For Each ch In s1
            If Char.IsPunctuation(ch) Or Char.IsWhiteSpace(ch) Then
                nWords += 1
            End If
        Next
        Console.WriteLine("The sentence{2}   {0}{2}has {1} words.",
                        s1, nWords, vbCrLf)
    End Sub
End Module
' The example displays the following output:
'       The sentence
'          This string consists of a single short sentence.
'       has 8 words.

Es posible que los valores de índice consecutivos no se correspondan con caracteres Unicode consecutivos, ya que un carácter Unicode se puede codificar como más de un Char objeto. En concreto, una cadena puede contener unidades de varios caracteres de texto formadas por un carácter base seguido de uno o varios caracteres combinados o por pares suplentes. Para trabajar con caracteres Unicode en lugar de Char objetos , use las System.Globalization.StringInfo clases y TextElementEnumerator , o el String.EnumerateRunes método y la Rune estructura . En el ejemplo siguiente se muestra la diferencia entre el código que funciona con objetos y código que funciona con Char caracteres Unicode. Compara el número de caracteres o elementos de texto en cada palabra de una oración. La cadena incluye dos secuencias de un carácter base seguido de un carácter combinado.

// First sentence of The Mystery of the Yellow Room, by Leroux.
string opening = "Ce n'est pas sans une certaine émotion que "+
                 "je commence à raconter ici les aventures " +
                 "extraordinaires de Joseph Rouletabille."; 
// Character counters.
int nChars = 0;
// Objects to store word count.
List<int> chars = new List<int>();
List<int> elements = new List<int>();

foreach (var ch in opening) {
   // Skip the ' character.
   if (ch == '\u0027') continue;
        
   if (Char.IsWhiteSpace(ch) | (Char.IsPunctuation(ch))) {
      chars.Add(nChars);
      nChars = 0;
   }
   else {
      nChars++;
   }
}

System.Globalization.TextElementEnumerator te = 
   System.Globalization.StringInfo.GetTextElementEnumerator(opening);
while (te.MoveNext()) {
   string s = te.GetTextElement();   
   // Skip the ' character.
   if (s == "\u0027") continue;
   if ( String.IsNullOrEmpty(s.Trim()) | (s.Length == 1 && Char.IsPunctuation(Convert.ToChar(s)))) {
      elements.Add(nChars);         
      nChars = 0;
   }
   else {
      nChars++;
   }
}

// Display character counts.
Console.WriteLine("{0,6} {1,20} {2,20}",
                  "Word #", "Char Objects", "Characters"); 
for (int ctr = 0; ctr < chars.Count; ctr++) 
   Console.WriteLine("{0,6} {1,20} {2,20}",
                     ctr, chars[ctr], elements[ctr]); 
// The example displays the following output:
//       Word #         Char Objects           Characters
//            0                    2                    2
//            1                    4                    4
//            2                    3                    3
//            3                    4                    4
//            4                    3                    3
//            5                    8                    8
//            6                    8                    7
//            7                    3                    3
//            8                    2                    2
//            9                    8                    8
//           10                    2                    1
//           11                    8                    8
//           12                    3                    3
//           13                    3                    3
//           14                    9                    9
//           15                   15                   15
//           16                    2                    2
//           17                    6                    6
//           18                   12                   12
open System
open System.Globalization

// First sentence of The Mystery of the Yellow Room, by Leroux.
let opening = "Ce n'est pas sans une certaine émotion que je commence à raconter ici les aventures extraordinaires de Joseph Rouletabille."
// Character counters.
let mutable nChars = 0
// Objects to store word count.
let chars = ResizeArray<int>()
let elements = ResizeArray<int>()

for ch in opening do
    // Skip the ' character.
    if ch <> '\u0027' then
        if Char.IsWhiteSpace ch || Char.IsPunctuation ch then
            chars.Add nChars
            nChars <- 0
        else
            nChars <- nChars + 1

let te = StringInfo.GetTextElementEnumerator opening
while te.MoveNext() do
    let s = te.GetTextElement()
    // Skip the ' character.
    if s <> "\u0027" then
        if String.IsNullOrEmpty(s.Trim()) || (s.Length = 1 && Char.IsPunctuation(Convert.ToChar s)) then
            elements.Add nChars
            nChars <- 0
        else
            nChars <- nChars + 1

// Display character counts.
printfn "%6s %20s %20s" "Word #" "Char Objects " "Characters"
for i = 0 to chars.Count - 1 do
    printfn "%6d %20d %20d" i chars[i] elements[i]
// The example displays the following output:
//       Word #         Char Objects           Characters
//            0                    2                    2
//            1                    4                    4
//            2                    3                    3
//            3                    4                    4
//            4                    3                    3
//            5                    8                    8
//            6                    8                    7
//            7                    3                    3
//            8                    2                    2
//            9                    8                    8
//           10                    2                    1
//           11                    8                    8
//           12                    3                    3
//           13                    3                    3
//           14                    9                    9
//           15                   15                   15
//           16                    2                    2
//           17                    6                    6
//           18                   12                   12
Imports System.Collections.Generic
Imports System.Globalization

Module Example14
    Public Sub Main()
        ' First sentence of The Mystery of the Yellow Room, by Leroux.
        Dim opening As String = "Ce n'est pas sans une certaine émotion que " +
                              "je commence à raconter ici les aventures " +
                              "extraordinaires de Joseph Rouletabille."
        ' Character counters.
        Dim nChars As Integer = 0
        ' Objects to store word count.
        Dim chars As New List(Of Integer)()
        Dim elements As New List(Of Integer)()

        For Each ch In opening
            ' Skip the ' character.
            If ch = ChrW(&H27) Then Continue For

            If Char.IsWhiteSpace(ch) Or Char.IsPunctuation(ch) Then
                chars.Add(nChars)
                nChars = 0
            Else
                nChars += 1
            End If
        Next

        Dim te As TextElementEnumerator = StringInfo.GetTextElementEnumerator(opening)
        Do While te.MoveNext()
            Dim s As String = te.GetTextElement()
            ' Skip the ' character.
            If s = ChrW(&H27) Then Continue Do
            If String.IsNullOrEmpty(s.Trim()) Or (s.Length = 1 AndAlso Char.IsPunctuation(Convert.ToChar(s))) Then
                elements.Add(nChars)
                nChars = 0
            Else
                nChars += 1
            End If
        Loop

        ' Display character counts.
        Console.WriteLine("{0,6} {1,20} {2,20}",
                        "Word #", "Char Objects", "Characters")
        For ctr As Integer = 0 To chars.Count - 1
            Console.WriteLine("{0,6} {1,20} {2,20}",
                           ctr, chars(ctr), elements(ctr))
        Next
    End Sub
End Module
' The example displays the following output:
'    Word #         Char Objects           Characters
'         0                    2                    2
'         1                    4                    4
'         2                    3                    3
'         3                    4                    4
'         4                    3                    3
'         5                    8                    8
'         6                    8                    7
'         7                    3                    3
'         8                    2                    2
'         9                    8                    8
'        10                    2                    1
'        11                    8                    8
'        12                    3                    3
'        13                    3                    3
'        14                    9                    9
'        15                   15                   15
'        16                    2                    2
'        17                    6                    6
'        18                   12                   12

En este ejemplo se trabaja con elementos de texto mediante el StringInfo.GetTextElementEnumerator método y la TextElementEnumerator clase para enumerar todos los elementos de texto de una cadena. También puede recuperar una matriz que contenga el índice inicial de cada elemento de texto llamando al StringInfo.ParseCombiningCharacters método .

Para obtener más información sobre cómo trabajar con unidades de texto en lugar de valores individuales Char , vea Introducción a la codificación de caracteres en .NET.

Cadenas nulas y cadenas vacías

Una cadena declarada pero que no se ha asignado un valor es null. Al intentar llamar a métodos en esa cadena, se produce una NullReferenceExceptionexcepción . Una cadena null es diferente de una cadena vacía, que es una cadena cuyo valor es "" o String.Empty. En algunos casos, pasar una cadena nula o una cadena vacía como argumento en una llamada de método produce una excepción. Por ejemplo, pasar una cadena nula al Int32.Parse método produce un ArgumentNullExceptiony pasar una cadena vacía produce una FormatExceptionexcepción . En otros casos, un argumento de método puede ser una cadena nula o una cadena vacía. Por ejemplo, si proporciona una IFormattable implementación para una clase, desea comparar una cadena nula y una cadena vacía con el especificador de formato general ("G").

La String clase incluye los dos métodos de conveniencia siguientes que permiten probar si una cadena es o está null vacía:

  • IsNullOrEmpty, que indica si una cadena es null o es igual a String.Empty. Este método elimina la necesidad de usar código como el siguiente:

    if (str == null || str.Equals(String.Empty))
    
    if str = null || str.Equals String.Empty then
    
    If str Is Nothing OrElse str.Equals(String.Empty) Then
    
  • IsNullOrWhiteSpace, que indica si una cadena es null, es igual String.Emptya o consta exclusivamente de caracteres de espacio en blanco. Este método elimina la necesidad de usar código como el siguiente:

    if (str == null || str.Equals(String.Empty) || str.Trim().Equals(String.Empty))
    
    if str = null || str.Equals String.Empty || str.Trim().Equals String.Empty then
    
    If str Is Nothing OrElse str.Equals(String.Empty) OrElse str.Trim().Equals(String.Empty) Then
    

En el ejemplo siguiente se usa el IsNullOrEmpty método en la IFormattable.ToString implementación de una clase personalizada Temperature . El método admite las cadenas de formato "G", "C", "F" y "K". Si una cadena de formato vacía o una cadena de formato cuyo valor se null pasa al método , su valor se cambia a la cadena de formato "G".

public string ToString(string format, IFormatProvider provider) 
{
   if (String.IsNullOrEmpty(format)) format = "G";  
   if (provider == null) provider = CultureInfo.CurrentCulture;
   
   switch (format.ToUpperInvariant())
   {
      // Return degrees in Celsius.    
      case "G":
      case "C":
         return temp.ToString("F2", provider) + "°C";
      // Return degrees in Fahrenheit.
      case "F": 
         return (temp * 9 / 5 + 32).ToString("F2", provider) + "°F";
      // Return degrees in Kelvin.
      case "K":   
         return (temp + 273.15).ToString();
      default:
         throw new FormatException(
               String.Format("The {0} format string is not supported.", 
                             format));
   }                                   
}
member _.ToString(format: string, provider: IFormatProvider) =
    let format = 
        if String.IsNullOrEmpty format then "G" else format
    
    let provider: IFormatProvider = 
        if provider = null then CultureInfo.CurrentCulture else provider

    match format.ToUpperInvariant() with
    // Return degrees in Celsius.
    | "G"
    | "C" ->
        temp.ToString("F2", provider) + "°C"
    // Return degrees in Fahrenheit.
    | "F" ->
        (temp * 9. / 5. + 32.).ToString("F2", provider) + "°F"
    // Return degrees in Kelvin.
    | "K" ->
        (temp + 273.15).ToString()
    | _ ->
        raise (FormatException(String.Format("The {0} format string is not supported.",format)))
Public Overloads Function ToString(fmt As String, provider As IFormatProvider) As String _
               Implements IFormattable.ToString
    If String.IsNullOrEmpty(fmt) Then fmt = "G"
    If provider Is Nothing Then provider = CultureInfo.CurrentCulture

    Select Case fmt.ToUpperInvariant()
     ' Return degrees in Celsius.    
        Case "G", "C"
            Return temp.ToString("F2", provider) + "°C"
     ' Return degrees in Fahrenheit.
        Case "F"
            Return (temp * 9 / 5 + 32).ToString("F2", provider) + "°F"
     ' Return degrees in Kelvin.
        Case "K"
            Return (temp + 273.15).ToString()
        Case Else
            Throw New FormatException(
              String.Format("The {0} format string is not supported.",
                            fmt))
    End Select
End Function

Inmutabilidad y la clase StringBuilder

Un String objeto se denomina inmutable (solo lectura), porque su valor no se puede modificar después de crearlo. Los métodos que parecen modificar un String objeto devuelven realmente un nuevo String objeto que contiene la modificación.

Dado que las cadenas son inmutables, las rutinas de manipulación de cadenas que realizan incorporaciones repetidas o eliminaciones a lo que parece ser una sola cadena pueden ser exactamente una penalización significativa del rendimiento. Por ejemplo, el código siguiente usa un generador de números aleatorios para crear una cadena con 1000 caracteres en el intervalo 0x0001 para 0x052F. Aunque el código parece usar la concatenación de cadenas para anexar un nuevo carácter a la cadena existente denominada str, realmente crea un nuevo String objeto para cada operación de concatenación.

using System;
using System.IO;
using System.Text;

public class Example6
{
   public static void Main()
   {
      Random rnd = new Random();
      
      string str = String.Empty;
      StreamWriter sw = new StreamWriter(@".\StringFile.txt", 
                           false, Encoding.Unicode);

      for (int ctr = 0; ctr <= 1000; ctr++) {
         str += (char)rnd.Next(1, 0x0530);
         if (str.Length % 60 == 0)
            str += Environment.NewLine;          
      }                    
      sw.Write(str);
      sw.Close();
   }
}
open System
open System.IO
open System.Text

do
    let rnd = Random()

    let mutable str = String.Empty
    use sw = new StreamWriter(@".\StringFile.txt", false, Encoding.Unicode)
    for _ = 0 to 1000 do
        str <- str + (rnd.Next(1, 0x0530) |> char |> string)
        if str.Length % 60 = 0 then
            str <- str + Environment.NewLine
    sw.Write str
Imports System.IO
Imports System.Text

Module Example10
    Public Sub Main()
        Dim rnd As New Random()

        Dim str As String = String.Empty
        Dim sw As New StreamWriter(".\StringFile.txt",
                           False, Encoding.Unicode)

        For ctr As Integer = 0 To 1000
            str += ChrW(rnd.Next(1, &H530))
            If str.Length Mod 60 = 0 Then str += vbCrLf
        Next
        sw.Write(str)
        sw.Close()
    End Sub
End Module

Puede usar la StringBuilder clase en lugar de la String clase para las operaciones que realizan varios cambios en el valor de una cadena. A diferencia de las instancias de la String clase , StringBuilder los objetos son mutables; al concatenar, anexar o eliminar subcadenas de una cadena, las operaciones se realizan en una sola cadena. Cuando haya terminado de modificar el valor de un StringBuilder objeto, puede llamar a su StringBuilder.ToString método para convertirlo en una cadena. En el ejemplo siguiente se reemplaza el String usado en el ejemplo anterior para concatenar 1000 caracteres aleatorios en el intervalo para 0x0001 a 0x052F con un StringBuilder objeto .

using System;
using System.IO;
using System.Text;

public class Example10
{
   public static void Main()
   {
      Random rnd = new Random();
      StringBuilder sb = new StringBuilder();
      StreamWriter sw = new StreamWriter(@".\StringFile.txt", 
                                         false, Encoding.Unicode);

      for (int ctr = 0; ctr <= 1000; ctr++) {
         sb.Append((char)rnd.Next(1, 0x0530));
         if (sb.Length % 60 == 0)
            sb.AppendLine();          
      }                    
      sw.Write(sb.ToString());
      sw.Close();
   }
}
open System
open System.IO
open System.Text

do
    let rnd = Random()
    let sb = StringBuilder()
    use sw = new StreamWriter(@".\StringFile.txt", false, Encoding.Unicode)

    for _ = 0 to 1000 do
        sb.Append(rnd.Next(1, 0x0530) |> char) |> ignore
        if sb.Length % 60 = 0 then
            sb.AppendLine() |> ignore
    sw.Write(string sb)
Imports System.IO
Imports System.Text

Module Example11
    Public Sub Main()
        Dim rnd As New Random()
        Dim sb As New StringBuilder()
        Dim sw As New StreamWriter(".\StringFile.txt",
                                 False, Encoding.Unicode)

        For ctr As Integer = 0 To 1000
            sb.Append(ChrW(rnd.Next(1, &H530)))
            If sb.Length Mod 60 = 0 Then sb.AppendLine()
        Next
        sw.Write(sb.ToString())
        sw.Close()
    End Sub
End Module

Ordinal frente a operaciones sensibles a la referencia cultural

Los miembros de la String clase realizan operaciones ordinales o que distinguen referencia cultural (lingüística) en un String objeto . Una operación ordinal actúa en el valor numérico de cada Char objeto. Una operación que distingue la referencia cultural actúa sobre el valor del objeto y toma en cuenta las reglas de ordenación, formato y análisis específicas de la String referencia cultural. Las operaciones que distinguen la referencia cultural se ejecutan en el contexto de una referencia cultural declarada explícitamente o la referencia cultural actual implícita. Los dos tipos de operaciones pueden producir resultados muy diferentes cuando se realizan en la misma cadena.

.NET también admite operaciones de cadena lingüística que no distinguen referencias culturales mediante la referencia cultural invariable (CultureInfo.InvariantCulture), que se basa de forma flexible en la configuración de referencia cultural del idioma inglés independientemente de la región. A diferencia de otras System.Globalization.CultureInfo configuraciones, se garantiza que la configuración de la referencia cultural invariable siga siendo coherente en un solo equipo, desde el sistema al sistema y entre versiones de .NET. La referencia cultural invariable se puede ver como un tipo de caja negra que garantiza la estabilidad de las comparaciones de cadenas y el orden en todas las referencias culturales.

Importante

Si la aplicación toma una decisión de seguridad sobre un identificador simbólico, como un nombre de archivo o una canalización con nombre, o sobre datos persistentes, como los datos basados en texto en un archivo XML, la operación debe usar una comparación ordinal en lugar de una comparación que distingue la referencia cultural. Esto se debe a que una comparación sensible a la referencia cultural puede producir resultados diferentes en función de la referencia cultural en vigor, mientras que una comparación ordinal depende únicamente del valor binario de los caracteres comparados.

Importante

La mayoría de los métodos que realizan operaciones de cadena incluyen una sobrecarga que tiene un parámetro de tipo StringComparison, que permite especificar si el método realiza una operación ordinal o que distingue referencia cultural. En general, debe llamar a esta sobrecarga para que la intención de la llamada al método sea clara. Para obtener procedimientos recomendados e instrucciones para usar operaciones ordinales y sensibles a la referencia cultural en cadenas, consulte Procedimientos recomendados para usar cadenas.

Las operaciones de uso de mayúsculas y minúsculas, análisis y formato, comparación y ordenación, y las pruebas de igualdad pueden ser ordinales o sensibles a la referencia cultural. En las secciones siguientes se describe cada categoría de operación.

Sugerencia

Siempre debe llamar a una sobrecarga de método que haga que la intención de la llamada al método esté clara. Por ejemplo, en lugar de llamar al Compare(String, String) método para realizar una comparación que distingue la referencia cultural de dos cadenas mediante las convenciones de la referencia cultural actual, debe llamar al Compare(String, String, StringComparison) método con un valor de StringComparison.CurrentCulture para el comparisonType argumento . Para obtener más información, consulte Procedimientos recomendados para el uso de cadenas.

Puede descargar las tablas de ponderación de ordenación, un conjunto de archivos de texto que contienen información sobre los pesos de caracteres usados en las operaciones de ordenación y comparación, de los vínculos siguientes:

Uso de mayúsculas y minúsculas

Las reglas de mayúsculas y minúsculas determinan cómo cambiar la mayúscula de un carácter Unicode; por ejemplo, de minúsculas a mayúsculas. A menudo, se realiza una operación de uso de mayúsculas y minúsculas antes de una comparación de cadenas. Por ejemplo, una cadena puede convertirse en mayúsculas para que se pueda comparar con otra cadena en mayúsculas. Puede convertir los caracteres de una cadena en minúsculas llamando al ToLower método o ToLowerInvariant y puede convertirlos en mayúsculas llamando al ToUpper método o ToUpperInvariant . Además, puede usar el TextInfo.ToTitleCase método para convertir una cadena en mayúsculas y minúsculas.

Nota:

Sistemas .NET Core que se ejecutan solo en sistemas Linux y macOS: El comportamiento de intercalación de las referencias culturales de C y Posix siempre distingue mayúsculas de minúsculas porque estas referencias culturales no usan el orden de intercalación Unicode esperado. Se recomienda que utilice una referencia cultural que no sea de C o Posix para realizar operaciones de ordenación que tengan en cuenta la referencia cultural y no distingan mayúsculas y minúsculas.

Las operaciones de mayúsculas y minúsculas se pueden basar en las reglas de la referencia cultural actual, una referencia cultural especificada o la referencia cultural invariable. Dado que las asignaciones de casos pueden variar en función de la referencia cultural utilizada, el resultado de las operaciones de mayúsculas y minúsculas puede variar en función de la referencia cultural. Las diferencias reales en el uso de mayúsculas y minúsculas son de tres tipos:

  • Diferencias en el caso de la asignación de LATIN CAPITAL LETTER I (U+0049), LATIN SMALL LETTER I (U+0069), LATIN CAPITAL LETTER I WITH DOT ABOVE (U+0130) y LATIN SMALL LETTER DOTLESS I (U+0131). En las culturas tr-TR (Turco (Turquía)) y az-Latn-AZ (Azerbaiyán, Latino), y en las culturas tr, az y az-Latn neutral, el equivalente en minúscula de LA LETRA CAPITAL LATINA I es LATÍN SMALL LETTER DOTLESS I, y el equivalente en mayúsculas de LATIN SMALL LETTER I es LATIN SMALL LETTER I WITH DOT ABOVE. En todas las demás culturas, incluyendo la cultura invariable, LATIN SMALL LETTER I y LATIN CAPITAL LETTER I son minúsculas y equivalentes en mayúsculas.

    En el ejemplo siguiente se muestra cómo se puede producir un error en una comparación de cadenas diseñada para evitar el acceso al sistema de archivos si se basa en una comparación de mayúsculas y minúsculas que distingue referencias culturales. (Se deben usar las convenciones de mayúsculas y minúsculas de la referencia cultural invariable).

    using System;
    using System.Globalization;
    using System.Threading;
    
    public class Example1
    {
       const string disallowed = "file";
       
       public static void Main()
       {
          IsAccessAllowed(@"FILE:\\\c:\users\user001\documents\FinancialInfo.txt");
       }
    
       private static void IsAccessAllowed(String resource)
       {
          CultureInfo[] cultures = { CultureInfo.CreateSpecificCulture("en-US"),
                                     CultureInfo.CreateSpecificCulture("tr-TR") };
          String scheme = null;
          int index = resource.IndexOfAny( new Char[] { '\\', '/' } );
          if (index > 0) 
             scheme = resource.Substring(0, index - 1);
    
          // Change the current culture and perform the comparison.
          foreach (var culture in cultures) {
             Thread.CurrentThread.CurrentCulture = culture;
             Console.WriteLine("Culture: {0}", CultureInfo.CurrentCulture.DisplayName);
             Console.WriteLine(resource);
             Console.WriteLine("Access allowed: {0}", 
                               ! String.Equals(disallowed, scheme, StringComparison.CurrentCultureIgnoreCase));      
             Console.WriteLine();
          }   
       }
    }
    // The example displays the following output:
    //       Culture: English (United States)
    //       FILE:\\\c:\users\user001\documents\FinancialInfo.txt
    //       Access allowed: False
    //       
    //       Culture: Turkish (Turkey)
    //       FILE:\\\c:\users\user001\documents\FinancialInfo.txt
    //       Access allowed: True
    
    open System
    open System.Globalization
    open System.Threading
    
    let disallowed = "file"
    
    let isAccessAllowed (resource: string) =
        let cultures = 
            [| CultureInfo.CreateSpecificCulture "en-US"
               CultureInfo.CreateSpecificCulture "tr-TR" |]
        let index = resource.IndexOfAny [| '\\'; '/' |]
        let scheme =
            if index > 0 then
                resource.Substring(0, index - 1)
            else 
                null
    
        // Change the current culture and perform the comparison.
        for culture in cultures do
            Thread.CurrentThread.CurrentCulture <- culture
            printfn $"Culture: {CultureInfo.CurrentCulture.DisplayName}"
            printfn $"{resource}"
            printfn $"Access allowed: {String.Equals(disallowed, scheme, StringComparison.CurrentCultureIgnoreCase) |> not}"
            printfn ""
            
    isAccessAllowed @"FILE:\\\c:\users\user001\documents\FinancialInfo.txt"
    // The example displays the following output:
    //       Culture: English (United States)
    //       FILE:\\\c:\users\user001\documents\FinancialInfo.txt
    //       Access allowed: False
    //
    //       Culture: Turkish (Turkey)
    //       FILE:\\\c:\users\user001\documents\FinancialInfo.txt
    //       Access allowed: True
    
    Imports System.Globalization
    Imports System.Threading
    
    Module Example2
        Const disallowed = "file"
    
        Public Sub Main()
            IsAccessAllowed("FILE:\\\c:\users\user001\documents\FinancialInfo.txt")
        End Sub
    
        Private Sub IsAccessAllowed(resource As String)
            Dim cultures() As CultureInfo = {CultureInfo.CreateSpecificCulture("en-US"),
                                            CultureInfo.CreateSpecificCulture("tr-TR")}
            Dim scheme As String = Nothing
            Dim index As Integer = resource.IndexOfAny({"\"c, "/"c})
            If index > 0 Then scheme = resource.Substring(0, index - 1)
    
            ' Change the current culture and perform the comparison.
            For Each culture In cultures
                Thread.CurrentThread.CurrentCulture = culture
                Console.WriteLine("Culture: {0}", CultureInfo.CurrentCulture.DisplayName)
                Console.WriteLine(resource)
                Console.WriteLine("Access allowed: {0}",
                               Not String.Equals(disallowed, scheme, StringComparison.CurrentCultureIgnoreCase))
                Console.WriteLine()
            Next
        End Sub
    End Module
    ' The example displays the following output:
    '       Culture: English (United States)
    '       FILE:\\\c:\users\user001\documents\FinancialInfo.txt
    '       Access allowed: False
    '       
    '       Culture: Turkish (Turkey)
    '       FILE:\\\c:\users\user001\documents\FinancialInfo.txt
    '       Access allowed: True
    
  • Diferencias en las asignaciones de casos entre la referencia cultural invariable y todas las demás referencias culturales. En estos casos, el uso de las reglas de mayúsculas y minúsculas de la referencia cultural invariable para cambiar un carácter a mayúsculas o minúsculas devuelve el mismo carácter. Para todas las demás referencias culturales, devuelve un carácter diferente. Algunos de los caracteres afectados se enumeran en la tabla siguiente.

    Carácter Si se cambia a Devoluciones
    SIGNO DE MICRON (U+00B5) Mayúsculas LETRA MAYÚSCULA GRIEGA MU (U+-39C)
    LETRA MAYÚSCULA LATINA I CON PUNTO SUPERIOR (U+0130) Minúsculas LETRA PEQUEÑA LATINA I (U+0069)
    LETRA PEQUEÑA LATINA I SIN PUNTO (U+0131) Mayúsculas LETRA MAYÚSCULA LATINA I (U+0049)
    LETRA PEQUEÑA LATINA LONG S (U+017F) Mayúsculas LETRA MAYÚSCULA LATINA S (U+0053)
    LETRA MAYÚSCULA LATINA D CON LETRA Z PEQUEÑA CON CARON (U+01C5) Minúsculas LETRA PEQUEÑA LATINA DZ CON CARON (U+01C6)
    COMBINACIÓN DE YPOGEGRAMMENI GRIEGO (U+0345) Mayúsculas LETRA MAYÚSCULA GRIEGA IOTA (U+0399)
  • Diferencias en las asignaciones de mayúsculas y minúsculas de pares de mayúsculas y minúsculas de dos letras en el intervalo de caracteres ASCII. En la mayoría de las referencias culturales, un par de mayúsculas y minúsculas de dos letras es igual al par de mayúsculas o minúsculas equivalente. Esto no es cierto para los siguientes pares de dos letras en las referencias culturales siguientes, ya que en cada caso se comparan con un digrafo:

    • "lJ" y "nJ" en la cultura hr-HR (Croacia)).
    • "cH" en las referencias culturales cs-CZ (República Checa)) y sk-SK (Eslovaquia)).
    • "aA" en la cultura da-DK (Dinamarca)).
    • "cS", "dZ", "dZS", "nY", "sZ", "tY" y "zS" en la cultura hu-HU (Hungría)).
    • "cH" y "lL" en la cultura es-ES_tradnl (Español (España, Ordenación Tradicional)).
    • "cH", "gI", "kH", "nG" "nH", "pH", "qU', "tH" y "tR" en la cultura vi-VN (Vietnam)).

    Sin embargo, es inusual encontrar una situación en la que una comparación que distingue la referencia cultural de estos pares crea problemas, ya que estos pares son poco comunes en cadenas o identificadores fijos.

En el ejemplo siguiente se muestran algunas de las diferencias en las reglas de mayúsculas y minúsculas entre las referencias culturales al convertir cadenas en mayúsculas.

using System;
using System.Globalization;
using System.IO;

public class Example
{
   public static void Main()
   {
      StreamWriter sw = new StreamWriter(@".\case.txt");   
      string[] words = { "file", "sıfır", "Dženana" };
      CultureInfo[] cultures = { CultureInfo.InvariantCulture, 
                                 new CultureInfo("en-US"),  
                                 new CultureInfo("tr-TR") };

      foreach (var word in words) {
         sw.WriteLine("{0}:", word);
         foreach (var culture in cultures) {
            string name = String.IsNullOrEmpty(culture.Name) ? 
                                 "Invariant" : culture.Name;
            string upperWord = word.ToUpper(culture);
            sw.WriteLine("   {0,10}: {1,7} {2, 38}", name, 
                         upperWord, ShowHexValue(upperWord));
         }
         sw.WriteLine();  
      }
      sw.Close();
   }

   private static string ShowHexValue(string s)
   {
      string retval = null;
      foreach (var ch in s) {
         byte[] bytes = BitConverter.GetBytes(ch);
         retval += String.Format("{0:X2} {1:X2} ", bytes[1], bytes[0]);     
      }
      return retval;
   } 
}
// The example displays the following output:
//    file:
//        Invariant:    FILE               00 46 00 49 00 4C 00 45 
//            en-US:    FILE               00 46 00 49 00 4C 00 45 
//            tr-TR:    FİLE               00 46 01 30 00 4C 00 45 
//    
//    sıfır:
//        Invariant:   SıFıR         00 53 01 31 00 46 01 31 00 52 
//            en-US:   SIFIR         00 53 00 49 00 46 00 49 00 52 
//            tr-TR:   SIFIR         00 53 00 49 00 46 00 49 00 52 
//    
//    Dženana:
//        Invariant:  DžENANA   01 C5 00 45 00 4E 00 41 00 4E 00 41 
//            en-US:  DŽENANA   01 C4 00 45 00 4E 00 41 00 4E 00 41 
//            tr-TR:  DŽENANA   01 C4 00 45 00 4E 00 41 00 4E 00 41
open System
open System.Globalization
open System.IO

let showHexValue (s: string) =
    let mutable retval = ""
    for ch in s do
        let bytes = BitConverter.GetBytes ch
        retval <- retval + String.Format("{0:X2} {1:X2} ", bytes[1], bytes[0])
    retval

do
    use sw = new StreamWriter(@".\case.txt")
    let words = [| "file"; "sıfır"; "Dženana" |]
    let cultures = 
        [| CultureInfo.InvariantCulture 
           CultureInfo "en-US"
           CultureInfo "tr-TR" |]

    for word in words do
        sw.WriteLine("{0}:", word)
        for culture in cultures do
            let name =
                 if String.IsNullOrEmpty culture.Name then "Invariant" else culture.Name
            let upperWord = word.ToUpper culture
            sw.WriteLine("   {0,10}: {1,7} {2, 38}", name, upperWord, showHexValue upperWord)
        sw.WriteLine()
    sw.Close()

// The example displays the following output:
//    file:
//        Invariant:    FILE               00 46 00 49 00 4C 00 45
//            en-US:    FILE               00 46 00 49 00 4C 00 45
//            tr-TR:    FİLE               00 46 01 30 00 4C 00 45
//
//    sıfır:
//        Invariant:   SıFıR         00 53 01 31 00 46 01 31 00 52
//            en-US:   SIFIR         00 53 00 49 00 46 00 49 00 52
//            tr-TR:   SIFIR         00 53 00 49 00 46 00 49 00 52
//
//    Dženana:
//        Invariant:  DžENANA   01 C5 00 45 00 4E 00 41 00 4E 00 41
//            en-US:  DŽENANA   01 C4 00 45 00 4E 00 41 00 4E 00 41
//            tr-TR:  DŽENANA   01 C4 00 45 00 4E 00 41 00 4E 00 41
Imports System.Globalization
Imports System.IO

Module Example1
    Public Sub Main()
        Dim sw As New StreamWriter(".\case.txt")
        Dim words As String() = {"file", "sıfır", "Dženana"}
        Dim cultures() As CultureInfo = {CultureInfo.InvariantCulture,
                                        New CultureInfo("en-US"),
                                        New CultureInfo("tr-TR")}

        For Each word In words
            sw.WriteLine("{0}:", word)
            For Each culture In cultures
                Dim name As String = If(String.IsNullOrEmpty(culture.Name),
                                 "Invariant", culture.Name)
                Dim upperWord As String = word.ToUpper(culture)
                sw.WriteLine("   {0,10}: {1,7} {2, 38}", name,
                         upperWord, ShowHexValue(upperWord))

            Next
            sw.WriteLine()
        Next
        sw.Close()
    End Sub

    Private Function ShowHexValue(s As String) As String
        Dim retval As String = Nothing
        For Each ch In s
            Dim bytes() As Byte = BitConverter.GetBytes(ch)
            retval += String.Format("{0:X2} {1:X2} ", bytes(1), bytes(0))
        Next
        Return retval
    End Function
End Module
' The example displays the following output:
'    file:
'        Invariant:    FILE               00 46 00 49 00 4C 00 45 
'            en-US:    FILE               00 46 00 49 00 4C 00 45 
'            tr-TR:    FİLE               00 46 01 30 00 4C 00 45 
'    
'    sıfır:
'        Invariant:   SıFıR         00 53 01 31 00 46 01 31 00 52 
'            en-US:   SIFIR         00 53 00 49 00 46 00 49 00 52 
'            tr-TR:   SIFIR         00 53 00 49 00 46 00 49 00 52 
'    
'    Dženana:
'        Invariant:  DžENANA   01 C5 00 45 00 4E 00 41 00 4E 00 41 
'            en-US:  DŽENANA   01 C4 00 45 00 4E 00 41 00 4E 00 41 
'            tr-TR:  DŽENANA   01 C4 00 45 00 4E 00 41 00 4E 00 41

Análisis y formato

El formato y el análisis son operaciones inversas. Las reglas de formato determinan cómo convertir un valor, como una fecha y hora o un número, en su representación de cadena, mientras que las reglas de análisis determinan cómo convertir una representación de cadena en un valor como una fecha y hora. Las reglas de formato y análisis dependen de las convenciones culturales. En el ejemplo siguiente se muestra la ambigüedad que puede surgir al interpretar una cadena de fecha específica de la referencia cultural. Sin conocer las convenciones de la referencia cultural que se usó para generar una cadena de fecha, no es posible saber si 03/01/2011, 3/1/2011 y 01/03/2011 representan el 3 de enero de 2011 o el 1 de marzo de 2011.

using System;
using System.Globalization;

public class Example9
{
   public static void Main()
   {
      DateTime date = new DateTime(2011, 3, 1);
      CultureInfo[] cultures = { CultureInfo.InvariantCulture, 
                                 new CultureInfo("en-US"), 
                                 new CultureInfo("fr-FR") };

      foreach (var culture in cultures)
         Console.WriteLine("{0,-12} {1}", String.IsNullOrEmpty(culture.Name) ?
                           "Invariant" : culture.Name, 
                           date.ToString("d", culture));                                    
   }
}
// The example displays the following output:
//       Invariant    03/01/2011
//       en-US        3/1/2011
//       fr-FR        01/03/2011
open System
open System.Globalization

let date = DateTime(2011, 3, 1)
let cultures = 
      [| CultureInfo.InvariantCulture
         CultureInfo "en-US"
         CultureInfo "fr-FR" |]

for culture in cultures do
    printfn $"""{(if String.IsNullOrEmpty culture.Name then "Invariant" else culture.Name),-12} {date.ToString("d", culture)}"""
// The example displays the following output:
//       Invariant    03/01/2011
//       en-US        3/1/2011
//       fr-FR        01/03/2011
Imports System.Globalization

Module Example8
    Public Sub Main()
        Dim dat As Date = #3/1/2011#
        Dim cultures() As CultureInfo = {CultureInfo.InvariantCulture,
                                        New CultureInfo("en-US"),
                                        New CultureInfo("fr-FR")}

        For Each culture In cultures
            Console.WriteLine("{0,-12} {1}", If(String.IsNullOrEmpty(culture.Name),
                           "Invariant", culture.Name),
                           dat.ToString("d", culture))
        Next
    End Sub
End Module
' The example displays the following output:
'       Invariant    03/01/2011
'       en-US        3/1/2011
'       fr-FR        01/03/2011

Del mismo modo, como se muestra en el ejemplo siguiente, una sola cadena puede producir fechas diferentes en función de la referencia cultural cuyas convenciones se usan en la operación de análisis.

using System;
using System.Globalization;

public class Example15
{
   public static void Main()
   {
      string dateString = "07/10/2011";
      CultureInfo[] cultures = { CultureInfo.InvariantCulture, 
                                 CultureInfo.CreateSpecificCulture("en-GB"), 
                                 CultureInfo.CreateSpecificCulture("en-US") };
      Console.WriteLine("{0,-12} {1,10} {2,8} {3,8}\n", "Date String", "Culture", 
                                                 "Month", "Day");
      foreach (var culture in cultures) {
         DateTime date = DateTime.Parse(dateString, culture);
         Console.WriteLine("{0,-12} {1,10} {2,8} {3,8}", dateString, 
                           String.IsNullOrEmpty(culture.Name) ?
                           "Invariant" : culture.Name, 
                           date.Month, date.Day);
      }                      
   }
}
// The example displays the following output:
//       Date String     Culture    Month      Day
//       
//       07/10/2011    Invariant        7       10
//       07/10/2011        en-GB       10        7
//       07/10/2011        en-US        7       10
open System
open System.Globalization

let dateString = "07/10/2011"
let cultures = 
    [| CultureInfo.InvariantCulture
       CultureInfo.CreateSpecificCulture "en-GB"
       CultureInfo.CreateSpecificCulture "en-US" |]
printfn $"""{"Date String",-12} {"Culture",10} {"Month",8} {"Day",8}\n"""
for culture in cultures do
    let date = DateTime.Parse(dateString, culture)
    printfn $"""{dateString,-12} {(if String.IsNullOrEmpty culture.Name then "Invariant" else culture.Name),10} {date.Month,8} {date.Day,8}"""
// The example displays the following output:
//       Date String     Culture    Month      Day
//
//       07/10/2011    Invariant        7       10
//       07/10/2011        en-GB       10        7
//       07/10/2011        en-US        7       10
Imports System.Globalization

Module Example18
    Public Sub Main()
        Dim dateString As String = "07/10/2011"
        Dim cultures() As CultureInfo = {CultureInfo.InvariantCulture,
                                        CultureInfo.CreateSpecificCulture("en-GB"),
                                        CultureInfo.CreateSpecificCulture("en-US")}
        Console.WriteLine("{0,-12} {1,10} {2,8} {3,8}", "Date String", "Culture",
                                                 "Month", "Day")
        Console.WriteLine()
        For Each culture In cultures
            Dim dat As Date = DateTime.Parse(dateString, culture)
            Console.WriteLine("{0,-12} {1,10} {2,8} {3,8}", dateString,
                           If(String.IsNullOrEmpty(culture.Name),
                           "Invariant", culture.Name),
                           dat.Month, dat.Day)
        Next
    End Sub
End Module
' The example displays the following output:
'       Date String     Culture    Month      Day
'       
'       07/10/2011    Invariant        7       10
'       07/10/2011        en-GB       10        7
'       07/10/2011        en-US        7       10

Comparación y ordenación de cadenas

Las convenciones para comparar y ordenar cadenas varían de la referencia cultural a la referencia cultural. Por ejemplo, el criterio de ordenación puede basarse en fonéticas o en la representación visual de caracteres. En los idiomas de Este de Asia, los caracteres se ordenan teniendo en cuenta los trazos y el radical de los ideogramas. El criterio de ordenación también depende del orden que se emplea en los distintos idiomas y referencias culturales para el alfabeto. Por ejemplo, el idioma danés tiene un carácter "Æ" que se ordena después de la "Z" en el alfabeto. Además, las comparaciones pueden distinguir mayúsculas de minúsculas o distinguir mayúsculas de minúsculas y las reglas de mayúsculas y minúsculas pueden diferir según la referencia cultural. Por otro lado, la comparación ordinal usa los puntos de código Unicode de caracteres individuales de una cadena al comparar y ordenar cadenas.

Las reglas de ordenación determinan el orden alfabético de caracteres Unicode y cómo dos cadenas se comparan entre sí. Por ejemplo, el String.Compare(String, String, StringComparison) método compara dos cadenas en función del StringComparison parámetro . Si el valor del parámetro es StringComparison.CurrentCulture, el método realiza una comparación lingüística que usa las convenciones de la referencia cultural actual; si el valor del parámetro es StringComparison.Ordinal, el método realiza una comparación ordinal. Por lo tanto, como se muestra en el ejemplo siguiente, si la referencia cultural actual es inglés de EE. UU., la primera llamada al método (mediante la String.Compare(String, String, StringComparison) comparación que distingue la referencia cultural) considera "a" menor que "A", pero la segunda llamada al mismo método (mediante la comparación ordinal) considera "a" mayor que "A".

using System;
using System.Globalization;
using System.Threading;

public class Example2
{
   public static void Main()
   {
      Thread.CurrentThread.CurrentCulture = CultureInfo.CreateSpecificCulture("en-US");
      Console.WriteLine(String.Compare("A", "a", StringComparison.CurrentCulture));
      Console.WriteLine(String.Compare("A", "a", StringComparison.Ordinal));
   }
}
// The example displays the following output:
//       1
//       -32
open System
open System.Globalization
open System.Threading

Thread.CurrentThread.CurrentCulture <- CultureInfo.CreateSpecificCulture "en-US"
printfn $"""{String.Compare("A", "a", StringComparison.CurrentCulture)}"""
printfn $"""{String.Compare("A", "a", StringComparison.Ordinal)}"""
// The example displays the following output:
//       1
//       -32
Imports System.Globalization
Imports System.Threading

Module Example3
    Public Sub Main()
        Thread.CurrentThread.CurrentCulture = CultureInfo.CreateSpecificCulture("en-US")
        Console.WriteLine(String.Compare("A", "a", StringComparison.CurrentCulture))
        Console.WriteLine(String.Compare("A", "a", StringComparison.Ordinal))
    End Sub
End Module
' The example displays the following output:
'       1                                                                                     
'       -32

.NET admite reglas de ordenación de palabras, cadenas y ordinales:

  • Una operación de ordenación de palabras realiza una comparación de cadenas donde se tiene en cuenta la referencia cultural y donde ciertos caracteres Unicode no alfanuméricos pueden tener asignados pesos especiales. Por ejemplo, el guión (-) podría tener un peso muy pequeño asignado para que "coop" y "co-op" aparezcan entre sí en una lista ordenada. Para obtener una lista de los String métodos que comparan dos cadenas mediante reglas de ordenación de palabras, consulte la sección Operaciones de cadena por categoría .

  • Una ordenación de cadena también realiza una comparación que distingue la referencia cultural. Es similar a una ordenación de palabras, salvo que no hay casos especiales, y todos los símbolos nonalphanumeric vienen antes de todos los caracteres Unicode alfanuméricos. Se pueden comparar dos cadenas mediante reglas de ordenación de cadenas mediante una llamada a las sobrecargas del CompareInfo.Compare método que tienen un options parámetro que se proporciona un valor de CompareOptions.StringSort. Tenga en cuenta que este es el único método que proporciona .NET para comparar dos cadenas mediante reglas de ordenación de cadenas.

  • Una ordenación ordinal compara las cadenas basadas en el valor numérico de cada objeto Char en la cadena. Una comparación ordinal distingue mayúsculas de minúsculas automáticamente porque las versiones minúsculas y mayúsculas de un carácter tienen puntos de código diferentes. Sin embargo, si el caso no es importante, puede especificar una comparación ordinal que omita mayúsculas y minúsculas. Esto equivale a convertir la cadena en mayúsculas mediante la referencia cultural invariable y, a continuación, realizar una comparación ordinal en el resultado. Para obtener una lista de los String métodos que comparan dos cadenas mediante reglas de ordenación ordinal, consulte la sección Operaciones de cadena por categoría .

Una comparación que distingue referencias culturales es cualquier comparación que use explícita o implícitamente un CultureInfo objeto, incluida la referencia cultural invariable especificada por la CultureInfo.InvariantCulture propiedad . La referencia cultural implícita es la referencia cultural actual, especificada por las Thread.CurrentCulture propiedades y CultureInfo.CurrentCulture . Hay una variación considerable en el orden de los caracteres alfabéticos (es decir, caracteres para los que la Char.IsLetter propiedad devuelve true) entre referencias culturales. Puede especificar una comparación que tenga en cuenta la referencia cultural que usa las convenciones de una referencia cultural específica proporcionando un CultureInfo objeto a un método de comparación de cadenas como Compare(String, String, CultureInfo, CompareOptions). Puede especificar una comparación que tenga en cuenta la referencia cultural que usa las convenciones de la referencia cultural actual proporcionando StringComparison.CurrentCulture, StringComparison.CurrentCultureIgnoreCaseo cualquier miembro de la CompareOptions enumeración que no CompareOptions.Ordinal sea o CompareOptions.OrdinalIgnoreCase a una sobrecarga adecuada del Compare método. Normalmente, una comparación que distingue referencias culturales es adecuada para la ordenación, mientras que una comparación ordinal no es correcta. Una comparación ordinal suele ser adecuada para determinar si dos cadenas son iguales (es decir, para determinar la identidad), mientras que no es una comparación que distingue la referencia cultural.

En el ejemplo siguiente se muestra la diferencia entre la comparación de referencia cultural y ordinal. En el ejemplo se evalúan tres cadenas, "Apple", "Æble" y "AEble", mediante la comparación ordinal y las convenciones de las referencias culturales da-DK y en-US (cada una de las cuales es la referencia cultural predeterminada en el momento en que se llama al Compare método). Dado que el idioma danés trata el carácter "Æ" como una letra individual y lo ordena después de "Z" en el alfabeto, la cadena "Æble" es mayor que "Apple". Sin embargo, "Æble" no se considera equivalente a "AEble", por lo que "Æble" también es mayor que "AEble". La referencia cultural en-US no incluye la letra "Æ", pero la trata como equivalente a "AE", que explica por qué "Æble" es menor que "Apple", pero igual que "AEble". Por otro lado, la comparación ordinal considera que "Apple" es menor que "Æble" y "Æble" para ser mayor que "AEble".

using System;
using System.Globalization;
using System.Threading;

public class CompareStringSample
{
   public static void Main()
   {
      string str1 = "Apple";
      string str2 = "Æble"; 
      string str3 = "AEble";
      
      // Set the current culture to Danish in Denmark.
      Thread.CurrentThread.CurrentCulture = new CultureInfo("da-DK");
      Console.WriteLine("Current culture: {0}", 
                        CultureInfo.CurrentCulture.Name);
      Console.WriteLine("Comparison of {0} with {1}: {2}", 
                        str1, str2, String.Compare(str1, str2));
      Console.WriteLine("Comparison of {0} with {1}: {2}\n", 
                        str2, str3, String.Compare(str2, str3));
      
      // Set the current culture to English in the U.S.
      Thread.CurrentThread.CurrentCulture = new CultureInfo("en-US");
      Console.WriteLine("Current culture: {0}", 
                        CultureInfo.CurrentCulture.Name);
      Console.WriteLine("Comparison of {0} with {1}: {2}", 
                        str1, str2, String.Compare(str1, str2));
      Console.WriteLine("Comparison of {0} with {1}: {2}\n", 
                        str2, str3, String.Compare(str2, str3));
      
      // Perform an ordinal comparison.
      Console.WriteLine("Ordinal comparison");
      Console.WriteLine("Comparison of {0} with {1}: {2}", 
                        str1, str2, 
                        String.Compare(str1, str2, StringComparison.Ordinal));
      Console.WriteLine("Comparison of {0} with {1}: {2}", 
                        str2, str3, 
                        String.Compare(str2, str3, StringComparison.Ordinal));
   }
}
// The example displays the following output:
//       Current culture: da-DK
//       Comparison of Apple with Æble: -1
//       Comparison of Æble with AEble: 1
//       
//       Current culture: en-US
//       Comparison of Apple with Æble: 1
//       Comparison of Æble with AEble: 0
//       
//       Ordinal comparison
//       Comparison of Apple with Æble: -133
//       Comparison of Æble with AEble: 133
open System
open System.Globalization
open System.Threading

let str1 = "Apple"
let str2 = "Æble"
let str3 = "AEble"

// Set the current culture to Danish in Denmark.
Thread.CurrentThread.CurrentCulture <- CultureInfo "da-DK"
printfn $"Current culture: {CultureInfo.CurrentCulture.Name}"
printfn $"Comparison of {str1} with {str2}: {String.Compare(str1, str2)}"
printfn $"Comparison of {str2} with {str3}: {String.Compare(str2, str3)}\n"

// Set the current culture to English in the U.S.
Thread.CurrentThread.CurrentCulture <- CultureInfo "en-US"
printfn $"Current culture: {CultureInfo.CurrentCulture.Name}"
printfn $"Comparison of {str1} with {str2}: {String.Compare(str1, str2)}"
printfn $"Comparison of {str2} with {str3}: {String.Compare(str2, str3)}\n"

// Perform an ordinal comparison.
printfn "Ordinal comparison"
printfn $"Comparison of {str1} with {str2}: {String.Compare(str1, str2, StringComparison.Ordinal)}"
printfn $"Comparison of {str2} with {str3}: {String.Compare(str2, str3, StringComparison.Ordinal)}"
// The example displays the following output:
//       Current culture: da-DK
//       Comparison of Apple with Æble: -1
//       Comparison of Æble with AEble: 1
//
//       Current culture: en-US
//       Comparison of Apple with Æble: 1
//       Comparison of Æble with AEble: 0
//
//       Ordinal comparison
//       Comparison of Apple with Æble: -133
//       Comparison of Æble with AEble: 133
Imports System.Globalization
Imports System.Threading

Public Module Example6
    Public Sub Main()
        Dim str1 As String = "Apple"
        Dim str2 As String = "Æble"
        Dim str3 As String = "AEble"

        ' Set the current culture to Danish in Denmark.
        Thread.CurrentThread.CurrentCulture = New CultureInfo("da-DK")
        Console.WriteLine("Current culture: {0}",
                        CultureInfo.CurrentCulture.Name)
        Console.WriteLine("Comparison of {0} with {1}: {2}",
                        str1, str2, String.Compare(str1, str2))
        Console.WriteLine("Comparison of {0} with {1}: {2}",
                        str2, str3, String.Compare(str2, str3))
        Console.WriteLine()

        ' Set the current culture to English in the U.S.
        Thread.CurrentThread.CurrentCulture = New CultureInfo("en-US")
        Console.WriteLine("Current culture: {0}",
                        CultureInfo.CurrentCulture.Name)
        Console.WriteLine("Comparison of {0} with {1}: {2}",
                        str1, str2, String.Compare(str1, str2))
        Console.WriteLine("Comparison of {0} with {1}: {2}",
                        str2, str3, String.Compare(str2, str3))
        Console.WriteLine()

        ' Perform an ordinal comparison.
        Console.WriteLine("Ordinal comparison")
        Console.WriteLine("Comparison of {0} with {1}: {2}",
                        str1, str2,
                        String.Compare(str1, str2, StringComparison.Ordinal))
        Console.WriteLine("Comparison of {0} with {1}: {2}",
                        str2, str3,
                        String.Compare(str2, str3, StringComparison.Ordinal))
    End Sub
End Module
' The example displays the following output:
'       Current culture: da-DK
'       Comparison of Apple with Æble: -1
'       Comparison of Æble with AEble: 1
'       
'       Current culture: en-US
'       Comparison of Apple with Æble: 1
'       Comparison of Æble with AEble: 0
'       
'       Ordinal comparison
'       Comparison of Apple with Æble: -133
'       Comparison of Æble with AEble: 133

Use las siguientes instrucciones generales para elegir un método de comparación de cadenas o ordenación adecuado:

  • Si desea que las cadenas se ordenen en función de la referencia cultural del usuario, debe ordenarlas en función de las convenciones de la referencia cultural actual. Si cambia la referencia cultural del usuario, el orden de las cadenas ordenadas también cambiará en consecuencia. Por ejemplo, una aplicación de sinónimos siempre debe ordenar palabras en función de la referencia cultural del usuario.

  • Si desea que las cadenas se ordenen en función de las convenciones de una referencia cultural específica, debe ordenarlas proporcionando un CultureInfo objeto que represente esa referencia cultural a un método de comparación. Por ejemplo, en una aplicación diseñada para enseñar a los alumnos un idioma determinado, quiere que las cadenas se ordenen en función de las convenciones de una de las referencias culturales que hablan ese idioma.

  • Si desea que el orden de las cadenas permanezca sin cambios entre referencias culturales, debe ordenarlas en función de las convenciones de la referencia cultural invariable o usar una comparación ordinal. Por ejemplo, usaría una ordenación ordinal para organizar los nombres de archivos, procesos, exclusión mutua o canalizaciones con nombre.

  • Para una comparación que implique una decisión de seguridad (por ejemplo, si un nombre de usuario es válido), siempre debe realizar una prueba ordinal para obtener igualdad llamando a una sobrecarga del Equals método .

Nota:

Las reglas de ordenación y mayúsculas y minúsculas que se usan en la comparación de cadenas dependen de la versión de .NET. En .NET Core, la comparación de cadenas depende de la versión del estándar Unicode compatible con el sistema operativo subyacente. En .NET Framework 4.5 y versiones posteriores que se ejecutan en Windows 8 o versiones posteriores, la ordenación, el uso de mayúsculas y minúsculas, y la información de caracteres Unicode 6.0 se ajustan al estándar Unicode 6.0. En otros sistemas operativos Windows, se ajustan al estándar Unicode 5.0.

Para obtener más información sobre las reglas de ordenación de palabras, cadenas y ordinales, consulte el System.Globalization.CompareOptions tema. Para obtener recomendaciones adicionales sobre cuándo usar cada regla, consulte Procedimientos recomendados para usar cadenas.

Normalmente, no se llama a métodos de comparación de cadenas como Compare , por ejemplo, directamente para determinar el criterio de ordenación de las cadenas. En su lugar, se llama a los métodos de comparación mediante la ordenación de métodos como Array.Sort o List<T>.Sort. En el ejemplo siguiente se realizan cuatro operaciones de ordenación diferentes (ordenación de palabras mediante la referencia cultural actual, la ordenación de palabras mediante la referencia cultural invariable, la ordenación ordinal y la ordenación de cadenas mediante la referencia cultural invariable) sin llamar explícitamente a un método de comparación de cadenas, aunque especifican el tipo de comparación que se va a usar. Tenga en cuenta que cada tipo de ordenación genera una ordenación única de cadenas en su matriz.

using System;
using System.Collections;
using System.Collections.Generic;
using System.Globalization;
 
public class Example3
{
   public static void Main()
   {
      string[] strings = { "coop", "co-op", "cooperative", 
                           "co\u00ADoperative", "cœur", "coeur" };

      // Perform a word sort using the current (en-US) culture.
      string[] current = new string[strings.Length]; 
      strings.CopyTo(current, 0); 
      Array.Sort(current, StringComparer.CurrentCulture);

      // Perform a word sort using the invariant culture.
      string[] invariant = new string[strings.Length];
      strings.CopyTo(invariant, 0); 
      Array.Sort(invariant, StringComparer.InvariantCulture);

      // Perform an ordinal sort.
      string[] ordinal = new string[strings.Length];
      strings.CopyTo(ordinal, 0); 
      Array.Sort(ordinal, StringComparer.Ordinal);

      // Perform a string sort using the current culture.
      string[] stringSort = new string[strings.Length];
      strings.CopyTo(stringSort, 0); 
      Array.Sort(stringSort, new SCompare());

      // Display array values
      Console.WriteLine("{0,13} {1,13} {2,15} {3,13} {4,13}\n", 
                        "Original", "Word Sort", "Invariant Word", 
                        "Ordinal Sort", "String Sort");
      for (int ctr = 0; ctr < strings.Length; ctr++)
         Console.WriteLine("{0,13} {1,13} {2,15} {3,13} {4,13}", 
                           strings[ctr], current[ctr], invariant[ctr], 
                           ordinal[ctr], stringSort[ctr] );          
   }
}

// IComparer<String> implementation to perform string sort.
internal class SCompare : IComparer<String>
{
   public int Compare(string x, string y)
   {
      return CultureInfo.CurrentCulture.CompareInfo.Compare(x, y, CompareOptions.StringSort);
   }
}
// The example displays the following output:
//         Original     Word Sort  Invariant Word  Ordinal Sort   String Sort
//    
//             coop          cœur            cœur         co-op         co-op
//            co-op         coeur           coeur         coeur          cœur
//      cooperative          coop            coop          coop         coeur
//     co­operative         co-op           co-op   cooperative          coop
//             cœur   cooperative     cooperative  co­operative   cooperative
//            coeur  co­operative    co­operative          cœur  co­operative
open System
open System.Collections.Generic
open System.Globalization

// IComparer<String> implementation to perform string sort using an F# object expression.
let scompare = 
    { new IComparer<String> with
        member _.Compare(x, y) =
            CultureInfo.CurrentCulture.CompareInfo.Compare(x, y, CompareOptions.StringSort) }

let strings = [| "coop"; "co-op"; "cooperative"; "co\u00ADoperative"; "cœur"; "coeur" |]

// Perform a word sort using the current (en-US) culture.
let current = Array.copy strings
Array.Sort(current, StringComparer.CurrentCulture)

// Perform a word sort using the invariant culture.
let invariant = Array.copy strings
Array.Sort(invariant, StringComparer.InvariantCulture)

// Perform an ordinal sort.
let ordinal = Array.copy strings
Array.Sort(ordinal, StringComparer.Ordinal)

// Perform a string sort using the current culture.
let stringSort = Array.copy strings
Array.Sort(stringSort, scompare)

// Display array values
printfn "%13s %13s %15s %13s %13s\n" "Original" "Word Sort" "Invariant Word" "Ordinal Sort" "String Sort"
for i = 0 to strings.Length - 1 do
    printfn "%13s %13s %15s %13s %13s\n" strings[i] current[i] invariant[i] ordinal[i] stringSort[i]

// The example displays the following output:
//         Original     Word Sort  Invariant Word  Ordinal Sort   String Sort
//
//             coop          cœur            cœur         co-op         co-op
//            co-op         coeur           coeur         coeur          cœur
//      cooperative          coop            coop          coop         coeur
//     co­operative         co-op           co-op   cooperative          coop
//             cœur   cooperative     cooperative  co­operative   cooperative
//            coeur  co­operative    co­operative          cœur  co­operative
Imports System.Collections
Imports System.Collections.Generic
Imports System.Globalization

Module Example4
    Public Sub Main()
        Dim strings() As String = {"coop", "co-op", "cooperative",
                                  "co" + ChrW(&HAD) + "operative",
                                  "cœur", "coeur"}

        ' Perform a word sort using the current (en-US) culture.
        Dim current(strings.Length - 1) As String
        strings.CopyTo(current, 0)
        Array.Sort(current, StringComparer.CurrentCulture)

        ' Perform a word sort using the invariant culture.
        Dim invariant(strings.Length - 1) As String
        strings.CopyTo(invariant, 0)
        Array.Sort(invariant, StringComparer.InvariantCulture)

        ' Perform an ordinal sort.
        Dim ordinal(strings.Length - 1) As String
        strings.CopyTo(ordinal, 0)
        Array.Sort(ordinal, StringComparer.Ordinal)

        ' Perform a string sort using the current culture.
        Dim stringSort(strings.Length - 1) As String
        strings.CopyTo(stringSort, 0)
        Array.Sort(stringSort, New SCompare())

        ' Display array values
        Console.WriteLine("{0,13} {1,13} {2,15} {3,13} {4,13}",
                        "Original", "Word Sort", "Invariant Word",
                        "Ordinal Sort", "String Sort")
        Console.WriteLine()

        For ctr As Integer = 0 To strings.Length - 1
            Console.WriteLine("{0,13} {1,13} {2,15} {3,13} {4,13}",
                           strings(ctr), current(ctr), invariant(ctr),
                           ordinal(ctr), stringSort(ctr))
        Next
    End Sub
End Module

' IComparer<String> implementation to perform string sort.
Friend Class SCompare : Implements IComparer(Of String)
   Public Function Compare(x As String, y As String) As Integer _
                   Implements IComparer(Of String).Compare
      Return CultureInfo.CurrentCulture.CompareInfo.Compare(x, y, CompareOptions.StringSort)
   End Function
End Class
' The example displays the following output:
'         Original     Word Sort  Invariant Word  Ordinal Sort   String Sort
'    
'             coop          cœur            cœur         co-op         co-op
'            co-op         coeur           coeur         coeur          cœur
'      cooperative          coop            coop          coop         coeur
'     co­operative         co-op           co-op   cooperative          coop
'             cœur   cooperative     cooperative  co­operative   cooperative
'            coeur  co­operative    co­operative          cœur  co­operative

Sugerencia

Internamente, .NET usa claves de ordenación para admitir la comparación de cadenas culturalmente confidenciales. A cada carácter de una cadena se le otorgan varias categorías de prioridad de ordenación, entre las que se incluyen el orden alfabético, el uso de mayúsculas y minúsculas y los signos diacríticos. Una clave de ordenación, representada por la SortKey clase , proporciona un repositorio de estos pesos para una cadena determinada. Si la aplicación realiza un gran número de operaciones de búsqueda o ordenación en el mismo conjunto de cadenas, puede mejorar su rendimiento generando y almacenando claves de ordenación para todas las cadenas que usa. Cuando se requiere una operación de ordenación o comparación, se usan las claves de ordenación en lugar de las cadenas. Para obtener más información, vea la clase SortKey.

Si no especifica una convención de comparación de cadenas, los métodos de ordenación, como Array.Sort(Array) realizar una ordenación que distingue referencia cultural y distingue mayúsculas de minúsculas en cadenas. En el ejemplo siguiente se muestra cómo el cambio de la referencia cultural actual afecta al orden de las cadenas ordenadas en una matriz. Crea una matriz de tres cadenas. En primer lugar, se establece la propiedad System.Threading.Thread.CurrentThread.CurrentCulture en en-US y se llama al método Array.Sort(Array). El criterio de ordenación resultante se basa en las convenciones de ordenación de la referencia cultural Inglés (Estados Unidos). A continuación, el ejemplo establece la propiedad System.Threading.Thread.CurrentThread.CurrentCulture en da-DK y llama de nuevo al método Array.Sort. Observe que el criterio de ordenación resultante difiere del resultado de en-US porque usa las convenciones de ordenación correspondientes a la referencia cultural Danés (Dinamarca).

using System;
using System.Globalization;
using System.Threading;

public class ArraySort
{
   public static void Main(String[] args)
   {
      // Create and initialize a new array to store the strings.
      string[] stringArray = { "Apple", "Æble", "Zebra"};

      // Display the values of the array.
      Console.WriteLine( "The original string array:");
      PrintIndexAndValues(stringArray);

      // Set the CurrentCulture to "en-US".
      Thread.CurrentThread.CurrentCulture = new CultureInfo("en-US");
      // Sort the values of the array.
      Array.Sort(stringArray);

      // Display the values of the array.
      Console.WriteLine("After sorting for the culture \"en-US\":");
      PrintIndexAndValues(stringArray);

      // Set the CurrentCulture to "da-DK".
      Thread.CurrentThread.CurrentCulture = new CultureInfo("da-DK");
      // Sort the values of the Array.
      Array.Sort(stringArray);

      // Display the values of the array.
      Console.WriteLine("After sorting for the culture \"da-DK\":");
      PrintIndexAndValues(stringArray);
   }
   public static void PrintIndexAndValues(string[] myArray)
   {
      for (int i = myArray.GetLowerBound(0); i <=
            myArray.GetUpperBound(0); i++ )
         Console.WriteLine("[{0}]: {1}", i, myArray[i]);
      Console.WriteLine();
   }
}
// The example displays the following output:
//       The original string array:
//       [0]: Apple
//       [1]: Æble
//       [2]: Zebra
//
//       After sorting for the "en-US" culture:
//       [0]: Æble
//       [1]: Apple
//       [2]: Zebra
//
//       After sorting for the culture "da-DK":
//       [0]: Apple
//       [1]: Zebra
//       [2]: Æble
open System
open System.Globalization
open System.Threading

let printIndexAndValues (myArray: string[]) =
    for i = myArray.GetLowerBound 0 to myArray.GetUpperBound 0 do
        printfn $"[{i}]: {myArray[i]}" 
    printfn ""

// Create and initialize a new array to store the strings.
let stringArray = [| "Apple"; "Æble"; "Zebra" |]

// Display the values of the array.
printfn "The original string array:"
printIndexAndValues stringArray

// Set the CurrentCulture to "en-US".
Thread.CurrentThread.CurrentCulture <- CultureInfo "en-US"
// Sort the values of the array.
Array.Sort stringArray

// Display the values of the array.
printfn "After sorting for the culture \"en-US\":"
printIndexAndValues stringArray

// Set the CurrentCulture to "da-DK".
Thread.CurrentThread.CurrentCulture <- CultureInfo "da-DK"
// Sort the values of the Array.
Array.Sort stringArray

// Display the values of the array.
printfn "After sorting for the culture \"da-DK\":"
printIndexAndValues stringArray
// The example displays the following output:
//       The original string array:
//       [0]: Apple
//       [1]: Æble
//       [2]: Zebra
//
//       After sorting for the "en-US" culture:
//       [0]: Æble
//       [1]: Apple
//       [2]: Zebra
//
//       After sorting for the culture "da-DK":
//       [0]: Apple
//       [1]: Zebra
//       [2]: Æble
Imports System.Globalization
Imports System.IO
Imports System.Threading

Public Class TextToFile   
   Public Shared Sub Main()
      ' Creates and initializes a new array to store 
      ' these date/time objects.
      Dim stringArray() As String = { "Apple", "Æble", "Zebra"}
      
      ' Displays the values of the array.
      Console.WriteLine("The original string array:")
      PrintIndexAndValues(stringArray)
      
      ' Set the CurrentCulture to "en-US".
      Thread.CurrentThread.CurrentCulture = New CultureInfo("en-US")
      ' Sort the values of the Array.
      Array.Sort(stringArray)
      
      ' Display the values of the array.
      Console.WriteLine("After sorting for the ""en-US"" culture:")
      PrintIndexAndValues(stringArray)
      
      ' Set the CurrentCulture to "da-DK".
      Thread.CurrentThread.CurrentCulture = New CultureInfo("da-DK")
      ' Sort the values of the Array.
      Array.Sort(stringArray)
      
      ' Displays the values of the Array.
      Console.WriteLine("After sorting for the culture ""da-DK"":")
      PrintIndexAndValues(stringArray)
   End Sub

   Public Shared Sub PrintIndexAndValues(myArray() As String)
      For i As Integer = myArray.GetLowerBound(0) To myArray.GetUpperBound(0)
         Console.WriteLine("[{0}]: {1}", i, myArray(i))
      Next
      Console.WriteLine()
   End Sub 
End Class
' The example displays the following output:
'       The original string array:
'       [0]: Apple
'       [1]: Æble
'       [2]: Zebra
'       
'       After sorting for the "en-US" culture:
'       [0]: Æble
'       [1]: Apple
'       [2]: Zebra
'       
'       After sorting for the culture "da-DK":
'       [0]: Apple
'       [1]: Zebra
'       [2]: Æble

Advertencia

Si el propósito principal de comparar cadenas es determinar si son iguales, debe llamar al String.Equals método . Normalmente, debe usar Equals para realizar una comparación ordinal. El String.Compare método está pensado principalmente para ordenar cadenas.

Los métodos de búsqueda de cadenas, como String.StartsWith y String.IndexOf, también pueden realizar comparaciones de cadenas ordinales o sensibles a la referencia cultural. En el ejemplo siguiente se muestran las diferencias entre las comparaciones ordinales y sensibles a la referencia cultural mediante el IndexOf método . Una búsqueda que distingue la referencia cultural en la que la referencia cultural actual es inglés (Estados Unidos) considera que la subcadena "oe" coincide con la ligadura "eur". Dado que un guión suave (U+00AD) es un carácter de ancho cero, la búsqueda trata el guion suave como equivalente a String.Empty y encuentra una coincidencia al principio de la cadena. Por otro lado, una búsqueda ordinal no encuentra ninguna coincidencia en ninguno de los casos.

using System;

public class Example8
{
   public static void Main()
   {
      // Search for "oe" and "œu" in "œufs" and "oeufs".
      string s1 = "œufs";
      string s2 = "oeufs";
      FindInString(s1, "oe", StringComparison.CurrentCulture);
      FindInString(s1, "oe", StringComparison.Ordinal);
      FindInString(s2, "œu", StringComparison.CurrentCulture);
      FindInString(s2, "œu", StringComparison.Ordinal);
      Console.WriteLine();
      
      string s3 = "co\u00ADoperative";
      FindInString(s3, "\u00AD", StringComparison.CurrentCulture);
      FindInString(s3, "\u00AD", StringComparison.Ordinal);
   }

   private static void FindInString(string s, string substring, StringComparison options)
   {
      int result = s.IndexOf(substring, options);
      if (result != -1)
         Console.WriteLine("'{0}' found in {1} at position {2}", 
                           substring, s, result);
      else
         Console.WriteLine("'{0}' not found in {1}", 
                           substring, s);                                                  
   }
}
// The example displays the following output:
//       'oe' found in œufs at position 0
//       'oe' not found in œufs
//       'œu' found in oeufs at position 0
//       'œu' not found in oeufs
//       
//       '­' found in co­operative at position 0
//       '­' found in co­operative at position 2
open System

let findInString (s: string) (substring: string) (options: StringComparison) =
    let result = s.IndexOf(substring, options)
    if result <> -1 then
        printfn $"'{substring}' found in {s} at position {result}"
    else
        printfn $"'{substring}' not found in {s}"

// Search for "oe" and "œu" in "œufs" and "oeufs".
let s1 = "œufs"
let s2 = "oeufs"
findInString s1 "oe" StringComparison.CurrentCulture
findInString s1 "oe" StringComparison.Ordinal
findInString s2 "œu" StringComparison.CurrentCulture
findInString s2 "œu" StringComparison.Ordinal
printfn ""

let s3 = "co\u00ADoperative"
findInString s3 "\u00AD" StringComparison.CurrentCulture
findInString s3 "\u00AD" StringComparison.Ordinal

// The example displays the following output:
//       'oe' found in œufs at position 0
//       'oe' not found in œufs
//       'œu' found in oeufs at position 0
//       'œu' not found in oeufs
//
//       '­' found in co­operative at position 0
//       '­' found in co­operative at position 2
Module Example5
    Public Sub Main()
        ' Search for "oe" and "œu" in "œufs" and "oeufs".
        Dim s1 As String = "œufs"
        Dim s2 As String = "oeufs"
        FindInString(s1, "oe", StringComparison.CurrentCulture)
        FindInString(s1, "oe", StringComparison.Ordinal)
        FindInString(s2, "œu", StringComparison.CurrentCulture)
        FindInString(s2, "œu", StringComparison.Ordinal)
        Console.WriteLine()

        Dim softHyphen As String = ChrW(&HAD)
        Dim s3 As String = "co" + softHyphen + "operative"
        FindInString(s3, softHyphen, StringComparison.CurrentCulture)
        FindInString(s3, softHyphen, StringComparison.Ordinal)
    End Sub

    Private Sub FindInString(s As String, substring As String,
                            options As StringComparison)
        Dim result As Integer = s.IndexOf(substring, options)
        If result <> -1 Then
            Console.WriteLine("'{0}' found in {1} at position {2}",
                           substring, s, result)
        Else
            Console.WriteLine("'{0}' not found in {1}",
                           substring, s)
        End If
    End Sub
End Module
' The example displays the following output:
'       'oe' found in œufs at position 0
'       'oe' not found in œufs
'       'œu' found in oeufs at position 0
'       'œu' not found in oeufs
'       
'       '­' found in co­operative at position 0
'       '­' found in co­operative at position 2

Buscar en cadenas

Los métodos de búsqueda de cadenas, como String.StartsWith y String.IndexOf, también pueden realizar comparaciones de cadenas ordinales o sensibles a la referencia cultural para determinar si se encuentra un carácter o una subcadena en una cadena especificada.

Los métodos de búsqueda de la String clase que buscan un carácter individual, como el IndexOf método, o uno de un conjunto de caracteres, como el IndexOfAny método , realizan una búsqueda ordinal. Para realizar una búsqueda que tenga en cuenta la referencia cultural de un carácter, debe llamar a un CompareInfo método como CompareInfo.IndexOf(String, Char) o CompareInfo.LastIndexOf(String, Char). Tenga en cuenta que los resultados de la búsqueda de un carácter mediante la comparación ordinal y sensible a la referencia cultural pueden ser muy diferentes. Por ejemplo, una búsqueda de un carácter Unicode precomponido como la ligadura "Æ" (U+00C6) podría coincidir con cualquier aparición de sus componentes en la secuencia correcta, como "AE" (U+041U+0045), dependiendo de la referencia cultural. En el ejemplo siguiente se muestra la diferencia entre los String.IndexOf(Char) métodos y CompareInfo.IndexOf(String, Char) al buscar un carácter individual. La ligadura "æ" (U+00E6) se encuentra en la cadena "aérea" cuando se usan las convenciones de la referencia cultural en-US, pero no cuando se usan las convenciones de la referencia cultural da-DK o al realizar una comparación ordinal.

using System;
using System.Globalization;

public class Example17
{
   public static void Main()
   {
      String[] cultureNames = { "da-DK", "en-US" };
      CompareInfo ci;
      String str = "aerial";
      Char ch = 'æ';  // U+00E6
      
      Console.Write("Ordinal comparison -- ");
      Console.WriteLine("Position of '{0}' in {1}: {2}", ch, str,
                        str.IndexOf(ch));
      
      foreach (var cultureName in cultureNames) {
         ci = CultureInfo.CreateSpecificCulture(cultureName).CompareInfo;
         Console.Write("{0} cultural comparison -- ", cultureName);
         Console.WriteLine("Position of '{0}' in {1}: {2}", ch, str,
                           ci.IndexOf(str, ch));
      }
   }
}
// The example displays the following output:
//       Ordinal comparison -- Position of 'æ' in aerial: -1
//       da-DK cultural comparison -- Position of 'æ' in aerial: -1
//       en-US cultural comparison -- Position of 'æ' in aerial: 0
open System.Globalization

let cultureNames = [| "da-DK"; "en-US" |]
let str = "aerial"
let ch = 'æ'  // U+00E6

printf "Ordinal comparison -- "
printfn $"Position of '{ch}' in {str}: {str.IndexOf ch}"
                  
for cultureName in cultureNames do
    let ci = CultureInfo.CreateSpecificCulture(cultureName).CompareInfo
    printf $"{cultureName} cultural comparison -- "
    printfn $"Position of '{ch}' in {str}: {ci.IndexOf(str, ch)}"
// The example displays the following output:
//       Ordinal comparison -- Position of 'æ' in aerial: -1
//       da-DK cultural comparison -- Position of 'æ' in aerial: -1
//       en-US cultural comparison -- Position of 'æ' in aerial: 0
Imports System.Globalization

Module Example19
    Public Sub Main()
        Dim cultureNames() As String = {"da-DK", "en-US"}
        Dim ci As CompareInfo
        Dim str As String = "aerial"
        Dim ch As Char = "æ"c  ' U+00E6

        Console.Write("Ordinal comparison -- ")
        Console.WriteLine("Position of '{0}' in {1}: {2}", ch, str,
                        str.IndexOf(ch))

        For Each cultureName In cultureNames
            ci = CultureInfo.CreateSpecificCulture(cultureName).CompareInfo
            Console.Write("{0} cultural comparison -- ", cultureName)
            Console.WriteLine("Position of '{0}' in {1}: {2}", ch, str,
                           ci.IndexOf(str, ch))
        Next
    End Sub
End Module
' The example displays the following output:
'       Ordinal comparison -- Position of 'æ' in aerial: -1
'       da-DK cultural comparison -- Position of 'æ' in aerial: -1
'       en-US cultural comparison -- Position of 'æ' in aerial: 0

Por otro lado, String los métodos de clase que buscan una cadena en lugar de un carácter realizan una búsqueda que distingue referencia cultural si las opciones de búsqueda no se especifican explícitamente mediante un parámetro de tipo StringComparison. La única excepción es Contains, que realiza una búsqueda ordinal.

Prueba de igualdad

Use el String.Compare método para determinar la relación de dos cadenas en el criterio de ordenación. Normalmente, se trata de una operación que distingue la referencia cultural. En cambio, llame al String.Equals método para probar la igualdad. Dado que la prueba de igualdad suele comparar la entrada del usuario con alguna cadena conocida, como un nombre de usuario válido, una contraseña o una ruta de acceso del sistema de archivos, normalmente es una operación ordinal.

Advertencia

Es posible probar la igualdad llamando al String.Compare método y determinando si el valor devuelto es cero. Sin embargo, no se recomienda esta práctica. Para determinar si dos cadenas son iguales, debe llamar a una de las sobrecargas del String.Equals método . La sobrecarga preferida a la que llamar es el método de instancia Equals(String, StringComparison) o el método estático Equals(String, String, StringComparison) , ya que ambos métodos incluyen un System.StringComparison parámetro que especifica explícitamente el tipo de comparación.

En el ejemplo siguiente se muestra el peligro de realizar una comparación sensible a la referencia cultural para la igualdad cuando se debe usar una ordinal en su lugar. En este caso, la intención del código es prohibir el acceso del sistema de archivos desde direcciones URL que comienzan por "FILE://" o "file://" realizando una comparación sin distinción entre mayúsculas y minúsculas del principio de una dirección URL con la cadena "FILE://". Sin embargo, si se realiza una comparación sensible a la referencia cultural cultural con la referencia cultural turca (Turquía) en una dirección URL que comienza por "file://", se produce un error en la comparación de igualdad, ya que el equivalente en mayúsculas turco de la "i" minúscula es "İ" en lugar de "I". Como resultado, se permite accidentalmente el acceso al sistema de archivos. Por otro lado, si se realiza una comparación ordinal, se deniega la comparación de igualdad y se deniega el acceso al sistema de archivos.

using System;
using System.Globalization;
using System.Threading;

public class Example4
{
   public static void Main()
   {
      Thread.CurrentThread.CurrentCulture = CultureInfo.CreateSpecificCulture("tr-TR");      

      string filePath = "file://c:/notes.txt";
      
      Console.WriteLine("Culture-sensitive test for equality:");
      if (! TestForEquality(filePath, StringComparison.CurrentCultureIgnoreCase))
         Console.WriteLine("Access to {0} is allowed.", filePath);
      else
         Console.WriteLine("Access to {0} is not allowed.", filePath);
      
      Console.WriteLine("\nOrdinal test for equality:");
      if (! TestForEquality(filePath, StringComparison.OrdinalIgnoreCase))
         Console.WriteLine("Access to {0} is allowed.", filePath);
      else
         Console.WriteLine("Access to {0} is not allowed.", filePath);
   }

   private static bool TestForEquality(string str, StringComparison cmp)
   {
      int position = str.IndexOf("://");
      if (position < 0) return false;

      string substring = str.Substring(0, position);  
      return substring.Equals("FILE", cmp);
   }
}
// The example displays the following output:
//       Culture-sensitive test for equality:
//       Access to file://c:/notes.txt is allowed.
//       
//       Ordinal test for equality:
//       Access to file://c:/notes.txt is not allowed.
open System
open System.Globalization
open System.Threading

let testForEquality (str: string) (cmp: StringComparison) =
    let position = str.IndexOf "://"
    if position < 0 then false
    else
        let substring = str.Substring(0, position)
        substring.Equals("FILE", cmp)

Thread.CurrentThread.CurrentCulture <- CultureInfo.CreateSpecificCulture "tr-TR"

let filePath = "file://c:/notes.txt"

printfn "Culture-sensitive test for equality:"
if not (testForEquality filePath StringComparison.CurrentCultureIgnoreCase) then
    printfn $"Access to {filePath} is allowed."
else
    printfn $"Access to {filePath} is not allowed."

printfn "\nOrdinal test for equality:"
if not (testForEquality filePath StringComparison.OrdinalIgnoreCase) then
    printfn $"Access to {filePath} is allowed."
else
    printfn $"Access to {filePath} is not allowed."

// The example displays the following output:
//       Culture-sensitive test for equality:
//       Access to file://c:/notes.txt is allowed.
//
//       Ordinal test for equality:
//       Access to file://c:/notes.txt is not allowed.
Imports System.Globalization
Imports System.Threading

Module Example7
    Public Sub Main()
        Thread.CurrentThread.CurrentCulture = CultureInfo.CreateSpecificCulture("tr-TR")

        Dim filePath As String = "file://c:/notes.txt"

        Console.WriteLine("Culture-sensitive test for equality:")
        If Not TestForEquality(filePath, StringComparison.CurrentCultureIgnoreCase) Then
            Console.WriteLine("Access to {0} is allowed.", filePath)
        Else
            Console.WriteLine("Access to {0} is not allowed.", filePath)
        End If
        Console.WriteLine()

        Console.WriteLine("Ordinal test for equality:")
        If Not TestForEquality(filePath, StringComparison.OrdinalIgnoreCase) Then
            Console.WriteLine("Access to {0} is allowed.", filePath)
        Else
            Console.WriteLine("Access to {0} is not allowed.", filePath)
        End If
    End Sub

    Private Function TestForEquality(str As String, cmp As StringComparison) As Boolean
        Dim position As Integer = str.IndexOf("://")
        If position < 0 Then Return False

        Dim substring As String = str.Substring(0, position)
        Return substring.Equals("FILE", cmp)
    End Function
End Module
' The example displays the following output:
'       Culture-sensitive test for equality:
'       Access to file://c:/notes.txt is allowed.
'       
'       Ordinal test for equality:
'       Access to file://c:/notes.txt is not allowed.

Normalización

Algunos caracteres Unicode tienen varias representaciones. Por ejemplo, cualquiera de los siguientes puntos de código puede representar la letra "ắ":

  • U+1EAF
  • U+0103 U+0301
  • U+0061 U+0306 U+0301

Varias representaciones de un solo carácter complican la búsqueda, la ordenación, la coincidencia y otras operaciones de cadena.

El estándar Unicode define un proceso denominado normalización que devuelve una representación binaria de un carácter Unicode para cualquiera de sus representaciones binarias equivalentes. La normalización puede usar varios algoritmos, denominados formularios de normalización, que siguen diferentes reglas. .NET admite formularios de normalización Unicode C, D, KC y KD. Cuando las cadenas se han normalizado en el mismo formulario de normalización, se pueden comparar mediante la comparación ordinal.

Una comparación ordinal es una comparación binaria del valor escalar Unicode de los objetos correspondientes Char en cada cadena. La String clase incluye una serie de métodos que pueden realizar una comparación ordinal, incluidos los siguientes:

Puede determinar si una cadena se normaliza para normalizar el formulario C llamando al String.IsNormalized() método o puede llamar al String.IsNormalized(NormalizationForm) método para determinar si una cadena se normaliza en un formulario de normalización especificado. También puede llamar al String.Normalize() método para convertir una cadena en el formulario de normalización C, o bien puede llamar al String.Normalize(NormalizationForm) método para convertir una cadena en un formulario de normalización especificado. Para obtener información paso a paso sobre cómo normalizar y comparar cadenas, consulte los Normalize() métodos y Normalize(NormalizationForm) .

En el ejemplo sencillo siguiente se muestra la normalización de cadenas. Define la letra "ố" de tres maneras diferentes en tres cadenas diferentes y usa una comparación ordinal para determinar que cada cadena difiere de las otras dos cadenas. A continuación, convierte cada cadena en los formularios de normalización admitidos y, de nuevo, realiza una comparación ordinal de cada cadena en un formulario de normalización especificado. En cada caso, la segunda prueba de igualdad muestra que las cadenas son iguales.

using System;
using System.Globalization;
using System.IO;
using System.Text;

public class Example13
{
   private static StreamWriter sw;
   
   public static void Main()
   {
      sw = new StreamWriter(@".\TestNorm1.txt");

      // Define three versions of the same word. 
      string s1 = "sống";        // create word with U+1ED1
      string s2 = "s\u00F4\u0301ng";
      string s3 = "so\u0302\u0301ng";

      TestForEquality(s1, s2, s3);      
      sw.WriteLine();

      // Normalize and compare strings using each normalization form.
      foreach (string formName in Enum.GetNames(typeof(NormalizationForm)))
      {
         sw.WriteLine("Normalization {0}:\n", formName); 
         NormalizationForm nf = (NormalizationForm) Enum.Parse(typeof(NormalizationForm), formName);
         string[] sn = NormalizeStrings(nf, s1, s2, s3);
         TestForEquality(sn);           
         sw.WriteLine("\n");                                        
      }
      
      sw.Close();   
   }

   private static void TestForEquality(params string[] words)
   {
      for (int ctr = 0; ctr <= words.Length - 2; ctr++)
         for (int ctr2 = ctr + 1; ctr2 <= words.Length - 1; ctr2++) 
            sw.WriteLine("{0} ({1}) = {2} ({3}): {4}", 
                         words[ctr], ShowBytes(words[ctr]),
                         words[ctr2], ShowBytes(words[ctr2]),
                         words[ctr].Equals(words[ctr2], StringComparison.Ordinal));
   }

   private static string ShowBytes(string str)
   {
      string result = null;
      foreach (var ch in str)
         result += $"{(ushort)ch:X4} ";
      return result.Trim();            
   } 
   
   private static string[] NormalizeStrings(NormalizationForm nf, params string[] words)
   {
      for (int ctr = 0; ctr < words.Length; ctr++)
         if (! words[ctr].IsNormalized(nf))
            words[ctr] = words[ctr].Normalize(nf); 
      return words;   
   }
}
// The example displays the following output:
//       sống (0073 1ED1 006E 0067) = sống (0073 00F4 0301 006E 0067): False
//       sống (0073 1ED1 006E 0067) = sống (0073 006F 0302 0301 006E 0067): False
//       sống (0073 00F4 0301 006E 0067) = sống (0073 006F 0302 0301 006E 0067): False
//       
//       Normalization FormC:
//       
//       sống (0073 1ED1 006E 0067) = sống (0073 1ED1 006E 0067): True
//       sống (0073 1ED1 006E 0067) = sống (0073 1ED1 006E 0067): True
//       sống (0073 1ED1 006E 0067) = sống (0073 1ED1 006E 0067): True
//       
//       
//       Normalization FormD:
//       
//       sống (0073 006F 0302 0301 006E 0067) = sống (0073 006F 0302 0301 006E 0067): True
//       sống (0073 006F 0302 0301 006E 0067) = sống (0073 006F 0302 0301 006E 0067): True
//       sống (0073 006F 0302 0301 006E 0067) = sống (0073 006F 0302 0301 006E 0067): True
//       
//       
//       Normalization FormKC:
//       
//       sống (0073 1ED1 006E 0067) = sống (0073 1ED1 006E 0067): True
//       sống (0073 1ED1 006E 0067) = sống (0073 1ED1 006E 0067): True
//       sống (0073 1ED1 006E 0067) = sống (0073 1ED1 006E 0067): True
//       
//       
//       Normalization FormKD:
//       
//       sống (0073 006F 0302 0301 006E 0067) = sống (0073 006F 0302 0301 006E 0067): True
//       sống (0073 006F 0302 0301 006E 0067) = sống (0073 006F 0302 0301 006E 0067): True
//       sống (0073 006F 0302 0301 006E 0067) = sống (0073 006F 0302 0301 006E 0067): True
open System
open System.IO
open System.Text

do
    use sw = new StreamWriter(@".\TestNorm1.txt")

    let showBytes (str: string) =
        let mutable result = ""
        for ch in str do
            result <- result + $"{uint16 ch:X4} "
        result.Trim()
    
    let testForEquality (words: string[]) =
        for ctr = 0 to words.Length - 2 do
            for ctr2 = ctr + 1 to words.Length - 1 do
                sw.WriteLine("{0} ({1}) = {2} ({3}): {4}",
                            words[ctr], showBytes(words[ctr]),
                            words[ctr2], showBytes(words[ctr2]),
                            words[ctr].Equals(words[ctr2], StringComparison.Ordinal))

    let normalizeStrings nf (words: string[]) =
        for i = 0 to words.Length - 1 do
            if not (words[i].IsNormalized nf) then
                words[i] <- words[i].Normalize nf
        words

    // Define three versions of the same word.
    let s1 = "sống"        // create word with U+1ED1
    let s2 = "s\u00F4\u0301ng"
    let s3 = "so\u0302\u0301ng"

    testForEquality [| s1; s2; s3 |]
    sw.WriteLine()

    // Normalize and compare strings using each normalization form.
    for formName in Enum.GetNames typeof<NormalizationForm> do
        sw.WriteLine("Normalization {0}:\n", formName)
        let nf = Enum.Parse(typeof<NormalizationForm>, formName) :?> NormalizationForm
        let sn = normalizeStrings nf [| s1; s2; s3|]
        testForEquality sn
        sw.WriteLine "\n"

// The example displays the following output:
//       sống (0073 1ED1 006E 0067) = sống (0073 00F4 0301 006E 0067): False
//       sống (0073 1ED1 006E 0067) = sống (0073 006F 0302 0301 006E 0067): False
//       sống (0073 00F4 0301 006E 0067) = sống (0073 006F 0302 0301 006E 0067): False
//
//       Normalization FormC:
//
//       sống (0073 1ED1 006E 0067) = sống (0073 1ED1 006E 0067): True
//       sống (0073 1ED1 006E 0067) = sống (0073 1ED1 006E 0067): True
//       sống (0073 1ED1 006E 0067) = sống (0073 1ED1 006E 0067): True
//
//
//       Normalization FormD:
//
//       sống (0073 006F 0302 0301 006E 0067) = sống (0073 006F 0302 0301 006E 0067): True
//       sống (0073 006F 0302 0301 006E 0067) = sống (0073 006F 0302 0301 006E 0067): True
//       sống (0073 006F 0302 0301 006E 0067) = sống (0073 006F 0302 0301 006E 0067): True
//
//
//       Normalization FormKC:
//
//       sống (0073 1ED1 006E 0067) = sống (0073 1ED1 006E 0067): True
//       sống (0073 1ED1 006E 0067) = sống (0073 1ED1 006E 0067): True
//       sống (0073 1ED1 006E 0067) = sống (0073 1ED1 006E 0067): True
//
//
//       Normalization FormKD:
//
//       sống (0073 006F 0302 0301 006E 0067) = sống (0073 006F 0302 0301 006E 0067): True
//       sống (0073 006F 0302 0301 006E 0067) = sống (0073 006F 0302 0301 006E 0067): True
//       sống (0073 006F 0302 0301 006E 0067) = sống (0073 006F 0302 0301 006E 0067): True
Imports System.Globalization
Imports System.IO
Imports System.Text

Module Example16
    Private sw As StreamWriter

    Public Sub Main()
        sw = New StreamWriter(".\TestNorm1.txt")

        ' Define three versions of the same word. 
        Dim s1 As String = "sống"        ' create word with U+1ED1
        Dim s2 As String = "s" + ChrW(&HF4) + ChrW(&H301) + "ng"
        Dim s3 As String = "so" + ChrW(&H302) + ChrW(&H301) + "ng"

        TestForEquality(s1, s2, s3)
        sw.WriteLine()

        ' Normalize and compare strings using each normalization form.
        For Each formName In [Enum].GetNames(GetType(NormalizationForm))
            sw.WriteLine("Normalization {0}:", formName)
            Dim nf As NormalizationForm = CType([Enum].Parse(GetType(NormalizationForm), formName),
                                             NormalizationForm)
            Dim sn() As String = NormalizeStrings(nf, s1, s2, s3)
            TestForEquality(sn)
            sw.WriteLine(vbCrLf)
        Next

        sw.Close()
    End Sub

    Private Sub TestForEquality(ParamArray words As String())
        For ctr As Integer = 0 To words.Length - 2
            For ctr2 As Integer = ctr + 1 To words.Length - 1
                sw.WriteLine("{0} ({1}) = {2} ({3}): {4}",
                         words(ctr), ShowBytes(words(ctr)),
                         words(ctr2), ShowBytes(words(ctr2)),
                         words(ctr).Equals(words(ctr2), StringComparison.Ordinal))
            Next
        Next
    End Sub

    Private Function ShowBytes(str As String) As String
        Dim result As String = Nothing
        For Each ch In str
            result += String.Format("{0} ", Convert.ToUInt16(ch).ToString("X4"))
        Next
        Return result.Trim()
    End Function

    Private Function NormalizeStrings(nf As NormalizationForm, ParamArray words() As String) As String()
        For ctr As Integer = 0 To words.Length - 1
            If Not words(ctr).IsNormalized(nf) Then
                words(ctr) = words(ctr).Normalize(nf)
            End If
        Next
        Return words
    End Function
End Module
' The example displays the following output:
'       sống (0073 1ED1 006E 0067) = sống (0073 00F4 0301 006E 0067): False
'       sống (0073 1ED1 006E 0067) = sống (0073 006F 0302 0301 006E 0067): False
'       sống (0073 00F4 0301 006E 0067) = sống (0073 006F 0302 0301 006E 0067): False
'       
'       Normalization FormC:
'       
'       sống (0073 1ED1 006E 0067) = sống (0073 1ED1 006E 0067): True
'       sống (0073 1ED1 006E 0067) = sống (0073 1ED1 006E 0067): True
'       sống (0073 1ED1 006E 0067) = sống (0073 1ED1 006E 0067): True
'       
'       
'       Normalization FormD:
'       
'       sống (0073 006F 0302 0301 006E 0067) = sống (0073 006F 0302 0301 006E 0067): True
'       sống (0073 006F 0302 0301 006E 0067) = sống (0073 006F 0302 0301 006E 0067): True
'       sống (0073 006F 0302 0301 006E 0067) = sống (0073 006F 0302 0301 006E 0067): True
'       
'       
'       Normalization FormKC:
'       
'       sống (0073 1ED1 006E 0067) = sống (0073 1ED1 006E 0067): True
'       sống (0073 1ED1 006E 0067) = sống (0073 1ED1 006E 0067): True
'       sống (0073 1ED1 006E 0067) = sống (0073 1ED1 006E 0067): True
'       
'       
'       Normalization FormKD:
'       
'       sống (0073 006F 0302 0301 006E 0067) = sống (0073 006F 0302 0301 006E 0067): True
'       sống (0073 006F 0302 0301 006E 0067) = sống (0073 006F 0302 0301 006E 0067): True
'       sống (0073 006F 0302 0301 006E 0067) = sống (0073 006F 0302 0301 006E 0067): True

Para obtener más información sobre los formularios de normalización y normalización, vea System.Text.NormalizationForm, así como el anexo estándar Unicode n.º 15: Formularios de normalización Unicode y las preguntas más frecuentes sobre normalización en el sitio web de unicode.org.

Operaciones de cadena por categoría

La String clase proporciona miembros para comparar cadenas, probar cadenas de igualdad, buscar caracteres o subcadenas en una cadena, modificar una cadena, extraer subcadenas de una cadena, combinar cadenas, dar formato a valores, copiar una cadena y normalizar una cadena.

Comparación de cadenas

Puede comparar cadenas para determinar su posición relativa en el criterio de ordenación mediante los métodos siguientes String :

  • Compare devuelve un entero que indica la relación de una cadena a una segunda cadena en el criterio de ordenación.

  • CompareOrdinal devuelve un entero que indica la relación de una cadena a una segunda cadena basándose en una comparación de sus puntos de código.

  • CompareTo devuelve un entero que indica la relación de la instancia de cadena actual con una segunda cadena en el criterio de ordenación. El CompareTo(String) método proporciona las IComparable implementaciones y IComparable<T> para la String clase .

Prueba de la igualdad de cadenas

Llame al Equals método para determinar si dos cadenas son iguales. La instancia Equals(String, String, StringComparison) y las sobrecargas estáticas Equals(String, StringComparison) permiten especificar si la comparación distingue referencias culturales o ordinales y si se considera o se omiten mayúsculas y minúsculas. La mayoría de las pruebas de igualdad son ordinales y las comparaciones de igualdad que determinan el acceso a un recurso del sistema (como un objeto de sistema de archivos) siempre deben ser ordinales.

Buscar caracteres en una cadena

La String clase incluye dos tipos de métodos de búsqueda:

Advertencia

Si desea buscar una cadena para un patrón determinado en lugar de una subcadena específica, debe usar expresiones regulares. Para obtener más información, vea Expresiones regulares de .NET.

Modificación de una cadena

La String clase incluye los métodos siguientes que parecen modificar el valor de una cadena:

  • Insert inserta una cadena en la instancia actual String .

  • PadLeft inserta una o varias apariciones de un carácter especificado al principio de una cadena.

  • PadRight inserta una o varias apariciones de un carácter especificado al final de una cadena.

  • Remove elimina una subcadena de la instancia actual String .

  • Replace reemplaza una subcadena por otra subcadena en la instancia actual String .

  • ToLower y ToLowerInvariant convierten todos los caracteres de una cadena en minúsculas.

  • ToUpper y ToUpperInvariant convierten todos los caracteres de una cadena en mayúsculas.

  • Trim quita todas las apariciones de un carácter desde el principio y el final de una cadena.

  • TrimEnd quita todas las apariciones de un carácter del final de una cadena.

  • TrimStart quita todas las apariciones de un carácter desde el principio de una cadena.

Importante

Todos los métodos de modificación de cadenas devuelven un nuevo String objeto. No modifican el valor de la instancia actual.

Extracción de subcadenas de una cadena

El String.Split método separa una sola cadena en varias cadenas. Las sobrecargas del método permiten especificar varios delimitadores, limitar el número de subcadenas que extrae el método, recortar el espacio en blanco de las subcadenas y especificar si las cadenas vacías (que se producen cuando los delimitadores son adyacentes) se incluyen entre las cadenas devueltas.

Combinar cadenas

Los métodos siguientes String se pueden usar para la concatenación de cadenas:

  • Concat combina una o varias subcadenas en una sola cadena.
  • Join concatena una o varias subcadenas en un solo elemento y agrega un separador entre cada subcadena.

Valores de formato

El String.Format método usa la característica de formato compuesto para reemplazar uno o varios marcadores de posición en una cadena por la representación de cadena de algún objeto o valor. El Format método se usa a menudo para hacer lo siguiente:

  • Para insertar la representación de cadena de un valor numérico en una cadena.
  • Para insertar la representación de cadena de un valor de fecha y hora en una cadena.
  • Para insertar la representación de cadena de un valor de enumeración en una cadena.
  • Para insertar la representación de cadena de algún objeto que admita la IFormattable interfaz en una cadena.
  • Para justificar a la derecha o a la izquierda una subcadena en un campo dentro de una cadena mayor.

Para obtener información detallada sobre las operaciones y ejemplos de formato, consulte el resumen de Format sobrecarga.

Copiar una cadena

Puede llamar a los métodos siguientes String para realizar una copia de una cadena:

  • Clone devuelve una referencia a un objeto existente String .
  • Copy crea una copia de una cadena existente.
  • CopyTo copia una parte de una cadena en una matriz de caracteres.

Normalizar una cadena

En Unicode, un solo carácter puede tener varios puntos de código. La normalización convierte estos caracteres equivalentes en la misma representación binaria. El String.Normalize método realiza la normalización y el String.IsNormalized método determina si se normaliza una cadena.

Para obtener más información y un ejemplo, consulte la sección Normalización anteriormente en este artículo.