Un string en C# es una secuencia de caracteres UTF-16 (valores char). Es un tipo de referencia, pero se comporta como un valor en lo que importa: es inmutable, y == compara el texto en lugar de la identidad del objeto. string es la palabra clave de C# para el tipo .NET System.String; los dos son intercambiables.
Salida:
Porto
5
0
*****
hi
Porto has 5 letters
Los strings son inmutables
Ningún método cambia un string en el sitio. ToUpper, Replace, Trim y todos los demás métodos devuelven un string nuevo y dejan el original intacto. Olvidarse de usar el valor devuelto es un bug de strings muy común:
Salida:
[ maya ]
[MAYA]
tea
tea and cake
La inmutabilidad hace que los strings puedan compartirse sin riesgo entre hilos y usarse como claves de diccionario. El coste es que construir un string pieza a pieza en un bucle crea un string nuevo en cada paso; para eso, usa StringBuilder.
Length e índices
Length es una propiedad (sin paréntesis). El indexador s[i] devuelve el char de la posición i, contando desde 0, y es de solo lectura:
Salida:
7
A
1
IndexOutOfRangeException
XB-2931
C# 8 y posteriores también aceptan un índice desde el final: code[^1] es el último carácter, igual que code[code.Length - 1]. Para tomar varios caracteres a la vez, consulta substring.
Length cuenta unidades de código UTF-16, no lo que un lector ve como caracteres. La mayoría de las letras de la mayoría de los idiomas ocupan una unidad, pero los emoji y algunas escrituras poco comunes usan dos (un par suplente), así que "👍".Length es 2.
Comparar strings
== y != comparan los caracteres, distinguiendo mayúsculas y minúsculas. Para cualquier otra cosa, pasa un valor StringComparison que diga cómo comparar:
Salida:
False
False
True
True
apple first
True
False
False
True
Qué comparación usar:
Ordinalcompara los códigos numéricos de los caracteres. Es rápida, predecible e igual en todas las máquinas. Úsala para identificadores, nombres de archivo, claves, valores de protocolo y todo lo que no se muestre a una persona.OrdinalIgnoreCasees lo mismo, sin distinguir mayúsculas. Es la opción correcta para comprobaciones que no distinguen mayúsculas, como las extensiones de archivo o las cabeceras HTTP.CurrentCulture(yCurrentCultureIgnoreCase) sigue las reglas del idioma del usuario, así que ordena las palabras como lo haría un diccionario de ese idioma. Úsala para ordenar listas que se muestran a los usuarios.InvariantCultureusa reglas que tienen en cuenta la cultura pero no dependen de la configuración de idioma del usuario. Aun así depende de la biblioteca de globalización: el .NET moderno usa ICU, .NET Framework usa NLS de Windows, y los dos pueden ordenar algunos strings de forma distinta.
string.Compare(a, b) y a.CompareTo(b) sin un StringComparison usan la cultura actual, lo que hace que sus resultados varíen entre máquinas. Evita comparar con a.ToLower() == b.ToLower(): reserva dos strings nuevos y da respuestas incorrectas en algunas culturas (la i con y sin punto del turco es el caso clásico).
Llamar a a.Equals(b) cuando a es null lanza una NullReferenceException, mientras que a == b y el string.Equals(a, b) static manejan null sin problemas.
Caracteres de escape
Dentro de un literal de string normal, una barra invertida inicia una secuencia de escape:
| Escape | Significado |
|---|---|
\n | Salto de línea (line feed) |
\r | Retorno de carro |
\t | Tabulador |
\\ | Barra invertida |
\" | Comilla doble |
\' | Comilla simple (solo hace falta en un literal char) |
\0 | Carácter nulo |
\uXXXX | Carácter UTF-16 por un código hexadecimal de 4 dígitos, por ejemplo \u00e9 |
\U0001F44D | Carácter por un código hexadecimal de 8 dígitos; por encima de U+FFFF se convierte en dos valores char |
\xH a \xHHHH | Carácter por 1 a 4 dígitos hexadecimales (evítalo: la longitud es ambigua) |
\a, \b, \f, \v | Alerta, retroceso, avance de página, tabulador vertical |
\e | Carácter de escape, U+001B (C# 13) |
Salida:
Name: Ana
City: Porto
She said "hi"
C:\temp\report.txt
cafe = cafe
' is a quote char
Una secuencia no reconocida como "\d" es un error de compilación (CS1009, secuencia de escape no reconocida), que es lo que ocurre cuando una ruta de Windows o una expresión regular se escribe como un string normal.
Strings literales (verbatim) y strings multilínea
Poner el prefijo @ a un literal lo hace literal (verbatim): las barras invertidas son caracteres normales, y el string puede ocupar varias líneas. El único escape que queda es "", que produce una comilla doble.
Salida:
C:\Users\ana\Documents\notes.txt
\d{3}-\d{4}
He said "ready" and left.
Rua das Flores 12
4050-262 Porto
Portugal
first line
second line
Un string literal multilínea incluye todo lo que hay entre las comillas, incluida la indentación de las líneas de continuación, y por eso suelen escribirse pegados al margen como arriba. Los saltos de línea que contiene son los del archivo fuente, así que un archivo guardado con finales de línea de Windows produce \r\n.
C# 11 añadió los literales de string sin procesar, que resuelven los dos problemas. Empiezan y terminan con tres o más comillas dobles, no necesitan ningún escape y quitan la indentación que tengan las comillas de cierre:
// C# 11 and later
string json = """
{
"name": "Ana",
"path": "C:\temp"
}
""";
// The 4 spaces before the closing """ are removed from every line.
Si el propio contenido contiene """, empieza y termina con cuatro comillas. Los literales sin procesar también se combinan con la interpolación ($"""..."""); consulta interpolación de strings.
Null, vacío y espacios en blanco
Una variable string puede ser null (ningún string), vacía ("", longitud 0) o contener solo espacios en blanco. Dos métodos auxiliares static comprueban estos casos sin arriesgarse a una NullReferenceException:
Salida:
null empty: True blank: True
"" empty: True blank: True
" " empty: False blank: True
"Ana" empty: False blank: False
True
Para validar la entrada del usuario, string.IsNullOrWhiteSpace es casi siempre el que quieres. string.Empty y "" son el mismo valor; cuál escribir es cuestión de estilo.
Recorrer los caracteres
Un string es enumerable, así que foreach visita cada char. El tipo char tiene métodos static para clasificar caracteres:
Salida:
letters=6 digits=4 upper=1 symbols=1
!6202tesnuS
Unir strings
+ concatena, y funciona con cualquier tipo al otro lado (llama a ToString()). Para combinar muchos valores, prefiere la interpolación o string.Join:
Salida:
Ana Silva, 31
Ana Silva, 31
AnaSilva
tea | coffee | juice
Total: 23
Total: 5
Las dos últimas líneas muestran una trampa de precedencia: + se evalúa de izquierda a derecha, así que en cuanto el lado izquierdo es un string, cada + siguiente es una concatenación. Pon entre paréntesis la aritmética que va dentro de una concatenación.
Preguntas frecuentes
¿Cómo obtengo la longitud de un string en C#?
Usa la propiedad Length: "hello".Length es 5. Es una propiedad, no un método, así que no lleva paréntesis. Length cuenta unidades de código UTF-16, así que un emoji u otro carácter fuera del plano multilingüe básico cuenta como 2. Llamarla sobre un string null lanza una NullReferenceException.
¿Cómo comparo strings en C#?
a == b compara el texto y distingue mayúsculas y minúsculas. Para una igualdad que no las distinga, usa string.Equals(a, b, StringComparison.OrdinalIgnoreCase). Para ordenar strings usa string.Compare(a, b, StringComparison.Ordinal) o una comparación que tenga en cuenta la cultura, que devuelve un número negativo, cero o un número positivo.
¿Cómo escribo un string multilínea en C#?
Pon el prefijo @ al literal para hacerlo literal (verbatim): puede ocupar varias líneas, las barras invertidas son literales y una comilla doble se escribe como "". En C# 11 y posteriores, los literales de string sin procesar delimitados por """ también ocupan varias líneas, quitan la indentación común y no necesitan ningún escape. También puedes unir líneas con \n o con Environment.NewLine.
¿Qué es un string literal (verbatim) en C#?
Un literal de string con el prefijo @, como @"C:\Users\ana". Las secuencias de escape no se procesan, así que una barra invertida es solo una barra invertida, lo que lo hace la opción natural para las rutas de Windows y las expresiones regulares. El único escape dentro de él es "" para una comilla doble.
¿Qué diferencia hay entre string y String en C#?
Ninguna. string es el alias de palabra clave de C# para el tipo .NET System.String, igual que int es un alias de System.Int32. La convención es usar string en las declaraciones y string.IsNullOrEmpty(...) en las llamadas static, pero los dos compilan exactamente a lo mismo.
¿Qué caracteres de escape admite C#?
\n salto de línea, \r retorno de carro, \t tabulador, \\ barra invertida, \" comilla doble, \' comilla simple, \0 carácter nulo, \uXXXX un carácter UTF-16 por su código hexadecimal, \U0001F600 un carácter por un código de 8 dígitos (se convierte en un par suplente), \a alerta, \b retroceso, \f avance de página, \v tabulador vertical y \e (C# 13) escape. Una secuencia desconocida como \d es un error de compilación (CS1009), y por eso las expresiones regulares suelen escribirse como strings literales con @.