Conceptos básicos sobre cadenas (Guía de programación de C#)

Actualización: noviembre 2007

Una cadena es un objeto de tipo String cuyo valor es texto. Internamente, el texto se almacena como una colección de sólo lectura de objetos Char, cada uno de los cuales representa un carácter Unicode codificado en UTF-16. A diferencia de C y C++, al final de una cadena de C# no hay un carácter null de terminación; por lo tanto, una cadena de C# puede contener un número cualquiera de caracteres null incrustados ('\0'). La longitud de una cadena representa el número de caracteres independientemente de que estén formados por pares suplentes Unicode o no. Para obtener acceso a los puntos de código Unicode individuales de una cadena, utilice el objeto StringInfo.

string frente a System.String

En C#, la palabra clave string es un alias de String. Por lo tanto, String y string son equivalentes y puede utilizar la convención de nomenclatura que prefiera. La clase String proporciona numerosos métodos para crear, manipular y comparar cadenas de forma segura. Además, el lenguaje C# sobrecarga algunos operadores para simplificar operaciones comunes de las cadenas. Para obtener más información sobre la palabra clave, vea string (Referencia de C#). Para obtener más información sobre el tipo y sus métodos, vea String.

Declarar e inicializar cadenas

Puede declarar e inicializar cadenas de varias maneras, como se muestra en el ejemplo siguiente:

// Declare without initializing.
string message1;

// Initialize to null.
string message2 = null;

// Initialize as an empty string.
// Use the Empty constant instead of the literal "".
string message3 = System.String.Empty;

//Initialize with a regular string literal.
string oldPath = "c:\\Program Files\\Microsoft Visual Studio 8.0";

// Initialize with a verbatim string literal.
string newPath = @"c:\Program Files\Microsoft Visual Studio 9.0";

// Use System.String if you prefer.
System.String greeting = "Hello World!";

// In local variables (i.e. within a method body)
// you can use implicit typing.
var temp = "I'm still a strongly-typed System.String!";

// Use a const string to prevent 'message4' from
// being used to store another string value.
const string message4 = "You can't get rid of me!";

// Use the String constructor only when creating
// a string from a char*, char[], or sbyte*. See
// System.String documentation for details.
char[] letters = { 'A', 'B', 'C' };
string alphabet = new string(letters);

Tenga en cuenta que el operador new no se utiliza para crear un objeto de cadena, salvo cuando se inicialice la cadena con una matriz de caracteres.

Inicialice una cadena con el valor constante Empty para crear un nuevo objeto String cuya cadena tiene una longitud cero. La representación literal de cadena de una cadena de longitud cero es "". Mediante la inicialización de cadenas con el valor Empty en lugar de null, puede reducir las posibilidades de que se produzca una excepción NullReferenceException. Utilice el método estático IsNullOrEmpty(String) para comprobar el valor de una cadena antes de intentar tener acceso a ésta.

Inmutabilidad de los objetos de cadena

Los objetos de cadena son inmutables, es decir, no pueden modificarse una vez creados. Todos los métodos String y los operadores de C# que parecen modificar una cadena, en realidad devuelven los resultados en un nuevo objeto de cadena. En el ejemplo siguiente, cuando el contenido de s1 y s2 se concatena para formar una sola cadena, las dos cadenas originales no se modifican. El operador += crea una nueva cadena que contiene el contenido combinado. Ese nuevo objeto se asigna a la variable s1 y el objeto original asignado a s1 se libera para la recolección de elementos no utilizados, ya que ninguna otra variable contiene una referencia a él.

string s1 = "A string is more ";
string s2 = "than the sum of its chars.";

// Concatenate s1 and s2. This actually creates a new
// string object and stores it in s1, releasing the
// reference to the original object.
s1 += s2;

System.Console.WriteLine(s1);
// Output: A string is more than the sum of its chars.

Dado que "modificar" una cadena consiste en realidad en crear una cadena nueva, debe actuar con precaución al crear referencias a las cadenas. Si crea una referencia a una cadena y después "modifica" la cadena original, la referencia seguirá señalando al objeto original en lugar de al nuevo objeto que se creó cuando se modificó la cadena. En el siguiente código se muestra este comportamiento:

string s1 = "Hello ";
string s2 = s1;
s1 += "World";

System.Console.WriteLine(s2);
//Output: Hello

Para obtener más información sobre cómo crear cadenas nuevas basadas en modificaciones como operaciones de búsqueda y reemplazo en la cadena original, vea Cómo: Modificar el contenido de cadenas (Guía de programación de C#).

Literales de cadena regulares y textuales

Utilice literales de cadena regulares cuando tenga que incrustar caracteres de escape proporcionados por C#, como se muestra en el ejemplo siguiente:

string columns = "Column 1\tColumn 2\tColumn 3";
//Output: Column 1        Column 2        Column 3

string rows = "Row 1\r\nRow 2\r\nRow 3";
/* Output:
  Row 1
  Row 2
  Row 3
*/

string title = "\"The \u00C6olean Harp\", by Samuel Taylor Coleridge";
//Output: "The Æolean Harp", by Samuel Taylor Coleridge

Utilice cadenas textuales para mayor comodidad y una mejor legibilidad cuando el texto de la cadena contiene caracteres de barra diagonal inversa, por ejemplo en rutas de acceso de archivo. Dado que las cadenas textuales conservan los caracteres de nueva línea como parte del texto de la cadena, pueden utilizarse para inicializar cadenas de múltiples líneas. Utilice las comillas dobles para incrustar comillas en una cadena textual. En el ejemplo siguiente se muestran algunos usos habituales de las cadenas textuales:

         string filePath = @"C:\Users\scoleridge\Documents\";
         //Output: C:\Users\scoleridge\Documents\

         string text = @"My pensive SARA ! thy soft cheek reclined
Thus on mine arm, most soothing sweet it is
To sit beside our Cot,...";
         /* Output:
         My pensive SARA ! thy soft cheek reclined
            Thus on mine arm, most soothing sweet it is
            To sit beside our Cot,... 
         */

         string quote = @"Her name was ""Sara.""";
         //Output: Her name was "Sara."

Secuencias de escape de cadena

Secuencia de escape

Nombre del carácter

Codificación Unicode

\'

Comilla simple

0x0027

\"

Comilla doble

0x0022

\\

Barra diagonal inversa

0x005C

\0

Null

0x0000

\a

Alerta

0x0007

\b

Retroceso

0x0008

\f

Avance de página

0x000C

\n

Nueva línea

0x000A

\r

Retorno de carro

0x000D

\t

Tabulación horizontal

0x0009

\U

Secuencia de escape Unicode para pares suplentes.

\Unnnnnnnn

\u

Secuencia de escape Unicode

\u0041 = "A"

\v

Tabulación vertical

0x000B

\x

Secuencia de escape Unicode similar a "\u" a excepción de la longitud variable.

\x0041 = "A"

Nota:

En tiempo de compilación, las cadenas textuales se convierten en cadenas normales con las mismas secuencias de escape. Así, si aparece una cadena textual en la ventana de inspección del depurador, verá los caracteres de escape agregados por el compilador, no la versión literal del código fuente. Por ejemplo, la cadena textual @”C:\files.txt” aparecerá como “C:\\files.txt” en la ventana de inspección.

Cadenas de formato

Una cadena de formato es una cadena cuyo contenido puede determinarse dinámicamente en tiempo de ejecución. Para crear una cadena de formato se utiliza el método estático Format y se incrustan marcadores de posición entre llaves que se reemplazarán por otros valores en tiempo de ejecución. En el ejemplo siguiente se utiliza una cadena de formato para generar el resultado de cada iteración de un bucle:

class FormatString
{
    static void Main()
    {
        // Get user input.
        System.Console.WriteLine("Enter a number");
        string input = System.Console.ReadLine();

        // Convert the input string to an int.
        int j;
        System.Int32.TryParse(input, out j);

        // Write a different string each iteration.
        string s;
        for (int i = 0; i < 10; i++)
        {
            // A simple format string with no alignment formatting.
            s = System.String.Format("{0} times {1} = {2}", i, j, (i * j));
            System.Console.WriteLine(s);
        }

        //Keep the console window open in debug mode.
        System.Console.ReadKey();
    }
}

Una sobrecarga del método WriteLine toma una cadena de formato como parámetro. Por lo tanto, puede incrustar simplemente un literal de cadena de formato sin una llamada explícita al método. Sin embargo, si utiliza el método WriteLine para mostrar el resultado de la depuración en la ventana Resultados de Visual Studio, tiene que llamar explícitamente al método Format porque WriteLine sólo acepta una cadena, no una cadena de formato. Para obtener más información sobre las cadenas de formato, vea Aplicar formato a tipos.

Subcadenas

Una subcadena es una secuencia de caracteres cualquiera incluida en una cadena. Utilice el método Substring para crear una nueva cadena a partir de un segmento de la cadena original. Puede buscar una o más apariciones de una subcadena con el método IndexOf. Utilice el método Replace para reemplazar todas las apariciones de una subcadena especificada por una cadena nueva. Al igual que el método Substring, Replace devuelve en realidad una cadena nueva y no modifica la cadena original. Para obtener más información, vea Cómo: Buscar cadenas mediante los métodos String (Guía de programación de C#) y Cómo: Modificar el contenido de cadenas (Guía de programación de C#).

string s3 = "Visual C# Express";
System.Console.WriteLine(s3.Substring(7, 2));
// Output: "C#"

System.Console.WriteLine(s3.Replace("C#", "Basic"));
// Output: "Visual Basic Express"

// Index values are zero-based
int index = s3.IndexOf("C");
// index = 7

Tener acceso a los caracteres individuales

Puede utilizar la notación de matrices con un valor de índice para obtener acceso de sólo lectura a caracteres individuales, como en el ejemplo siguiente:

string s5 = "Printing backwards";

for (int i = 0; i < s5.Length; i++)
{
    System.Console.Write(s5[s5.Length - i - 1]);
}
// Output: "sdrawkcab gnitnirP"

Si los métodos String no proporcionan la funcionalidad necesaria para modificar caracteres individuales en una cadena, puede utilizar un objeto StringBuilder para modificar los caracteres individuales "en contexto" y crear a continuación una nueva cadena para almacenar los resultados mediante los métodos StringBuilder. En el ejemplo siguiente, suponga que debe modificar la cadena original de una forma determinada y almacenar a continuación los resultados para su uso futuro:

string question = "hOW DOES mICROSOFT wORD DEAL WITH THE cAPS lOCK KEY?";
System.Text.StringBuilder sb = new System.Text.StringBuilder(question);

for (int j = 0; j < sb.Length; j++)
{
    if (System.Char.IsLower(sb[j]) == true)
        sb[j] = System.Char.ToUpper(sb[j]);
    else if (System.Char.IsUpper(sb[j]) == true)
        sb[j] = System.Char.ToLower(sb[j]);
}
// Store the new string.
string corrected = sb.ToString();
System.Console.WriteLine(corrected);
// Output: How does Microsoft Word deal with the Caps Lock key?            

Cadenas nulas y cadenas vacías

Una cadena vacía es una instancia de un objeto System.String que contiene cero caracteres. Las cadenas vacías se utilizan habitualmente en distintos escenarios de programación para representar un campo de texto en blanco. Puede realizar llamadas a métodos en cadenas vacías porque son objetos System.String válidos. Las cadenas vacías se inicializan tal y como se indica a continuación:

string s = String.Empty;

Por el contrario, una cadena nula no hace referencia a una instancia de un objeto System.String y cualquier intento de llamar a un método en una cadena nula provoca una excepción NullReferenceException. Sin embargo, puede utilizar cadenas nulas en operaciones de concatenación y comparación con otras cadenas. Los ejemplos siguientes muestran algunos casos en los que se hace referencia a una cadena nula y no se produce una excepción:

static void Main()
{
    string str = "hello";
    string nullStr = null;
    string emptyStr = "a";

    string tempStr = str + nullStr; // tempStr = "hello"
    bool b = (emptyStr == nullStr);// b = false;
    string newStr = emptyStr + nullStr; // creates a new empty string
    int len = nullStr.Length; // throws NullReferenceException

}

Utilizar StringBuilder para crear cadenas de forma rápida

Las operaciones de cadena en .NET están muy optimizadas y, en la mayoría de los casos, no tienen un impacto significativo en el rendimiento. Sin embargo, en algunos escenarios, como en bucles de pequeñas dimensiones que se ejecutan cientos o miles de veces, las operaciones de cadena pueden afectar al rendimiento. La clase StringBuilder crea un búfer de cadena que proporciona un mayor rendimiento si el programa realiza muchas manipulaciones de cadenas. La cadena StringBuilder también permite reasignar los caracteres individuales, algo que el tipo de datos de cadena integrado no admite. Por ejemplo, este código cambia el contenido de una cadena sin crear una nueva cadena:

System.Text.StringBuilder sb = new System.Text.StringBuilder("Rat: the ideal pet");
sb[0] = 'C';
System.Console.WriteLine(sb.ToString());
System.Console.ReadLine();

//Outputs Cat: the ideal pet

En este ejemplo, se utiliza un objeto StringBuilder para crear una cadena a partir de un conjunto de tipos numéricos:

class TestStringBuilder
{
    static void Main()
    {
        System.Text.StringBuilder sb = new System.Text.StringBuilder();

        // Create a string composed of numbers 0 - 9
        for (int i = 0; i < 10; i++)
        {
            sb.Append(i.ToString());
        }
        System.Console.WriteLine(sb);  // displays 0123456789

        // Copy one character of the string (not possible with a System.String)
        sb[0] = sb[9];

        System.Console.WriteLine(sb);  // displays 9123456789
    }
}

Cadenas, métodos de extensión y LINQ

Dado que el tipo String implementa IEnumerable<T>, puede utilizar los métodos de extensión definidos en la clase Enumerable en las cadenas. Para evitar el desorden visual, estos métodos se excluyen de IntelliSense para el tipo String, pero están disponibles de todas formas. También puede utilizar expresiones de consulta LINQ en las cadenas. Para obtener más información, vea LINQ y cadenas.

Vea también

Tareas

Cómo: Buscar cadenas mediante expresiones regulares (Guía de programación de C#)

Cómo: Buscar cadenas mediante los métodos String (Guía de programación de C#)

Cómo: Dividir cadenas (Guía de programación de C#)

Conceptos

Guía de programación de C#

Otros recursos

Analizar cadenas