Stringhe e valori letterali stringa

Una stringa è un oggetto di tipo String il cui valore è testo. Internamente il testo viene archiviato come una raccolta di sola lettura sequenziale di oggetti Char. Nessun carattere di terminazione Null alla fine di una stringa C#; pertanto una stringa C# può contenere qualsiasi numero di caratteri Null incorporati ('\0'). La proprietà Length di una stringa rappresenta il numero di oggetti Char in essa contenuti e non il numero di caratteri Unicode. Per accedere ai singoli punti di codice Unicode in una stringa usare l'oggetto StringInfo.

string vs. System.String

In Visual Basic la parola chiave string è un alias per String. Pertanto, String e string sono equivalenti, indipendentemente dal fatto che sia consigliabile usare l'alias string fornito come funziona anche senza using System;. La classe String fornisce molti metodi per creare, modificare e confrontare stringhe in modo sicuro. Inoltre, il linguaggio C# esegue l'overload di alcuni operatori per semplificare le operazioni comuni sulle stringhe. Per altre informazioni sull'uso della parola chiave, vedere string. Per altre informazioni sul tipo e sui relativi metodi, vedere String.

Dichiarazione e inizializzazione di stringhe

È possibile dichiarare e inizializzare stringhe in vari modi, come mostrato nell'esempio seguente:

// 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);

Non si usa il nuovo operatore per creare un oggetto stringa, tranne quando si inizializza la stringa con una matrice di caratteri.

Inizializzare una stringa con il valore costante Empty per creare un nuovo oggetto String con stringa di lunghezza zero. La rappresentazione del valore letterale stringa di una stringa di lunghezza zero è "". L'inizializzazione di stringhe con il valore Empty anziché con null riduce le probabilità di un errore NullReferenceException. Usare il metodo statico IsNullOrEmpty(String) per verificare il valore di una stringa prima di provare ad accedere alla stringa.

Immutabilità delle stringhe

Gli oggetti stringa non sono modificabili: non possono essere modificati dopo la creazione. Tutti i metodi String e gli operatori C# che sembrano modificare una stringa in realtà restituiscono i risultati in un nuovo oggetto stringa. Nell'esempio seguente, quando il contenuto di s1 e s2 viene concatenato per formare un'unica stringa, le due stringhe originali restano immutate. L'operatore += crea una nuova stringa che contiene il contenuto delle due stringhe combinato. Il nuovo oggetto viene assegnato alla variabile s1 e l'oggetto originale assegnato a s1 viene rilasciato per l'operazione di Garbage Collection perché nessun'altra variabile contiene un riferimento a tale oggetto.

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.

Dato che una "modifica" della stringa è in effetti la creazione di una nuova stringa, è necessario prestare attenzione quando si creano riferimenti alle stringhe. Se si crea un riferimento a una stringa e quindi si "modifica" la stringa originale, il riferimento continuerà a puntare all'oggetto originale anziché al nuovo oggetto creato quando la stringa è stata modificata. Il codice seguente illustra questo comportamento:

string str1 = "Hello ";
string str2 = str1;
str1 += "World";

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

Per altre informazioni su come creare nuove stringhe basate su modifiche quali operazioni di ricerca e sostituzione sulla stringa originale, vedere Come modificare il contenuto della stringa.

Valori letterali stringa tra virgolette

I valori letterali stringa tra virgolette sono iniziali e terminano con un singolo carattere virgolette doppie (") sulla stessa riga. I valori letterali stringa tra virgolette sono più adatti per le stringhe che si adattano a una singola riga e non includono sequenze di escape. Un valore letterale stringa tra virgolette deve incorporare caratteri di escape, come illustrato nell'esempio seguente:

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

Valori letterali di stringa verbatim

I valori letterali stringa verbatim sono più pratici per stringhe a più righe, stringhe che contengono caratteri barra rovesciata o virgolette doppie incorporate. Le stringhe verbatim mantengono i nuovi caratteri di riga come parte del testo stringa. Usare virgolette doppie per incorporare una virgoletta in una stringa verbatim. L'esempio seguente mostra alcuni usi comuni delle stringhe verbatim:

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."

Valori letterali stringa non elaborati

A partire da C# 11, è possibile usare valori letterali stringa non elaborati per creare più facilmente stringhe multilinea o usare qualsiasi carattere che richiede sequenze di escape. I valori letterali stringa non elaborati eliminano la necessità di usare sequenze di escape. È possibile scrivere la stringa, inclusa la formattazione degli spazi vuoti, la modalità di visualizzazione nell'output. Valore letterale stringa non elaborato:

  • Inizia e termina con una sequenza di almeno tre caratteri virgolette doppie ("""). Sono consentiti più di tre caratteri consecutivi per iniziare e terminare la sequenza per supportare valori letterali stringa contenenti tre o più caratteri di virgolette ripetute.
  • I valori letterali stringa non elaborati a riga singola richiedono i caratteri virgolette di apertura e chiusura sulla stessa riga.
  • I valori letterali stringa non elaborati su più righe richiedono caratteri di virgolette di apertura e di chiusura sulla propria riga.
  • Nei valori letterali stringa non elaborati su più righe, tutti gli spazi vuoti a sinistra delle virgolette di chiusura vengono rimossi.

Gli esempi seguenti illustrano queste regole:

string singleLine = """Friends say "hello" as they pass by.""";
string multiLine = """
    "Hello World!" is typically the first program someone writes.
    """;
string embeddedXML = """
       <element attr = "content">
           <body style="normal">
               Here is the main text
           </body>
           <footer>
               Excerpts from "An amazing story"
           </footer>
       </element >
       """;
// The line "<element attr = "content">" starts in the first column.
// All whitespace left of that column is removed from the string.

string rawStringLiteralDelimiter = """"
    Raw string literals are delimited 
    by a string of at least three double quotes,
    like this: """
    """";

Gli esempi seguenti illustrano gli errori del compilatore segnalati in base a queste regole:

// CS8997: Unterminated raw string literal.
var multiLineStart = """This
    is the beginning of a string 
    """;

// CS9000: Raw string literal delimiter must be on its own line.
var multiLineEnd = """
    This is the beginning of a string """;

// CS8999: Line does not start with the same whitespace as the closing line
// of the raw string literal
var noOutdenting = """
    A line of text.
Trying to outdent the second line.
    """;

I primi due esempi non sono validi perché i valori letterali stringa non elaborati su più righe richiedono la sequenza di virgolette di apertura e chiusura sulla propria riga. Il terzo esempio non è valido perché il testo è rientrato dalla sequenza di virgolette di chiusura.

Quando si genera testo che include caratteri che richiedono sequenze di escape quando si usano valori letterali stringa delimitati o valori letterali stringa verbatim, è consigliabile prendere in considerazione i valori letterali stringa non elaborati. I valori letterali stringa non elaborati saranno più facili da leggere perché saranno più simili al testo di output. Si consideri ad esempio il codice seguente che include una stringa di JSON formattato:

string jsonString = """
{
  "Date": "2019-08-01T00:00:00-07:00",
  "TemperatureCelsius": 25,
  "Summary": "Hot",
  "DatesAvailable": [
    "2019-08-01T00:00:00-07:00",
    "2019-08-02T00:00:00-07:00"
  ],
  "TemperatureRanges": {
    "Cold": {
      "High": 20,
      "Low": -10
    },
    "Hot": {
      "High": 60,
      "Low": 20
    }
            },
  "SummaryWords": [
    "Cool",
    "Windy",
    "Humid"
  ]
}
""";

Confrontare il testo con il testo equivalente nell'esempio sulla serializzazione JSON, che non usa questa nuova funzionalità.

Sequenze di escape di stringa

Sequenza di escape Nome carattere Codifica Unicode
\' Virgoletta singola 0x0027
\" Virgoletta doppia 0x0022
\\ Barra rovesciata 0x005C
\0 Null 0x0000
\a Avviso 0x0007
\b Backspace 0x0008
\f Avanzamento carta 0x000C
\n Nuova riga 0x000A
\r Ritorno a capo 0x000D
\t Tabulazione orizzontale 0x0009
\v Tabulazione verticale 0x000B
\u Sequenza di escape Unicode (UTF-16) \uHHHH (intervallo: 0000 - FFFF; esempio: \u00E7 = "ç")
\U Sequenza di escape Unicode (UTF-32) \U00HHHHHH (intervallo: 000000 - 10FFFF; esempio: \U0001F47D = "👽")
\x Sequenza di escape Unicode simile a "\u", ma con lunghezza variabile \xH[H][H][H] (intervallo: 0 - FFFF; esempio: \x00E7 o \x0E7\xE7 = "ç")

Avviso

Quando si usa la sequenza di escape \x e si specificano meno di 4 cifre esadecimali, se i caratteri immediatamente seguenti la sequenza di escape sono cifre esadecimali valide (ad esempio 0-9, A-F e a-f), questi verranno interpretati come parte della sequenza di escape. Ad esempio, \xA1 produce "¡", ovvero il punto di codice U+00A1. Tuttavia, se il carattere successivo è "A" o "a", la sequenza di escape verrà invece interpretata come e \xA1A produce "ਚ", ovvero il punto di codice U+0A1A. In questi casi, specificando tutte e 4 le cifre esadecimali (ad esempio, \x00A1) si eviteranno possibili interpretazioni errate.

Nota

In fase di compilazione, le stringhe verbatim vengono convertite in stringhe normali con tutte le stesse sequenze di escape. Pertanto, se si visualizza una stringa verbatim nella finestra Espressioni di controllo del debugger, si vedranno i caratteri di escape aggiunti dal compilatore e non la versione verbatim del codice sorgente. Ad esempio, la stringa @"C:\files.txt" verbatim verrà visualizzata nella finestra espressioni di controllo come "C:\\files.txt".

Stringhe di formato

Una stringa di formato è una stringa il cui contenuto viene determinato in modo dinamico in fase di esecuzione. Le stringhe di formato vengono create incorporando segnaposto o espressioni interpolate all'interno di parentesi graffe in una stringa. Tutti gli elementi all'interno delle parentesi graffe ({...}) verranno risolti in un valore e nell'output come stringa formattata in fase di esecuzione. Esistono due metodi per creare stringhe di formato: interpolazione di stringhe e formattazione composita.

Interpolazione di stringhe

Le stringhe interpolate, disponibili in C# 6.0 e versioni successive, vengono identificate dal carattere speciale $ e includono le espressioni interpolate tra parentesi graffe. Se non si ha familiarità con l'interpolazione di stringhe, vedere l'esercitazione interattiva Interpolazione di stringhe - C# per una rapida panoramica.

Usare l'interpolazione di stringhe per migliorare la leggibilità e la gestibilità del codice. L'interpolazione di stringhe permette di ottenere gli stessi risultati del metodo String.Format, ma è più facile da usare e migliora la chiarezza inline.

var jh = (firstName: "Jupiter", lastName: "Hammon", born: 1711, published: 1761);
Console.WriteLine($"{jh.firstName} {jh.lastName} was an African American poet born in {jh.born}.");
Console.WriteLine($"He was first published in {jh.published} at the age of {jh.published - jh.born}.");
Console.WriteLine($"He'd be over {Math.Round((2018d - jh.born) / 100d) * 100d} years old today.");

// Output:
// Jupiter Hammon was an African American poet born in 1711.
// He was first published in 1761 at the age of 50.
// He'd be over 300 years old today.

A partire da C# 10, è possibile usare l'interpolazione di stringhe per inizializzare una stringa costante quando anche tutte le espressioni usate per i segnaposto sono stringhe costanti.

A partire da C# 11, è possibile combinare valori letterali stringa non elaborati con interpolazioni di stringhe. Iniziare e terminare la stringa di formato con tre o più virgolette doppie successive. Se la stringa di output deve contenere il { carattere o } , è possibile usare caratteri aggiuntivi $ per specificare quanti { caratteri e } iniziano e terminano un'interpolazione. Qualsiasi sequenza di meno { caratteri o } viene inclusa nell'output. Nell'esempio seguente viene illustrato come usare tale funzionalità per visualizzare la distanza di un punto dall'origine e posizionare il punto all'interno delle parentesi graffe:

int X = 2;
int Y = 3;

var pointMessage = $$"""The point {{{X}}, {{Y}}} is {{Math.Sqrt(X * X + Y * Y)}} from the origin.""";

Console.WriteLine(pointMessage);
// Output:
// The point {2, 3} is 3.605551275463989 from the origin.

Formattazione composita

String.Format utilizza segnaposto tra parentesi graffe per creare una stringa di formato. Questo esempio restituisce un output simile a quello del metodo di interpolazione di stringhe usato sopra.

var pw = (firstName: "Phillis", lastName: "Wheatley", born: 1753, published: 1773);
Console.WriteLine("{0} {1} was an African American poet born in {2}.", pw.firstName, pw.lastName, pw.born);
Console.WriteLine("She was first published in {0} at the age of {1}.", pw.published, pw.published - pw.born);
Console.WriteLine("She'd be over {0} years old today.", Math.Round((2018d - pw.born) / 100d) * 100d);

// Output:
// Phillis Wheatley was an African American poet born in 1753.
// She was first published in 1773 at the age of 20.
// She'd be over 300 years old today.

Per altre informazioni sulla formattazione dei tipi .NET, vedere Formattazione dei tipi in .NET.

Sottostringhe

Una sottostringa è qualsiasi sequenza di caratteri contenuta in una stringa. Usare il metodo Substring per creare una nuova stringa da una parte della stringa originale. È possibile cercare una o più occorrenze di una sottostringa tramite il metodo IndexOf. Usare il metodo Replace per sostituire tutte le occorrenze di una sottostringa specificata con una nuova stringa. Analogamente al Substring metodo , Replace restituisce effettivamente una nuova stringa e non modifica la stringa originale. Per altre informazioni, vedere Come cercare stringhe e Come modificare il contenuto della stringa.

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

Accesso a singoli caratteri

È possibile utilizzare la notazione di matrice con un valore di indice per ottenere l'accesso in sola lettura a singoli caratteri, come nell'esempio seguente:

string s5 = "Printing backwards";

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

Se i String metodi non forniscono la funzionalità che è necessario modificare i singoli caratteri in una stringa, è possibile usare un StringBuilder oggetto per modificare i singoli caratteri "sul posto" e quindi creare una nuova stringa per archiviare i risultati usando i StringBuilder metodi . Nell'esempio seguente presupporre che sia necessario modificare la stringa originale in un modo specifico e archiviare quindi i risultati per 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?

Stringhe Null e stringhe vuote

Una stringa vuota è un'istanza di un oggetto System.String che contiene zero caratteri. Le stringhe vuote sono utilizzate di frequente in diversi scenari di programmazione per rappresentare un campo di testo vuoto. È possibile chiamare metodi su stringhe vuote perché sono oggetti validi System.String . Le stringhe vuote vengono inizializzate come indicato di seguito:

string s = String.Empty;

Al contrario, una stringa Null non fa riferimento a un'istanza di un System.String oggetto e qualsiasi tentativo di chiamare un metodo su una stringa Null causa un oggetto NullReferenceException. È tuttavia possibile usare stringhe null nelle operazioni di concatenazione e confronto con altre stringhe. Gli esempi seguenti illustrano alcuni casi in cui un riferimento a una stringa Null esegue e non genera un'eccezione:

string str = "hello";
string nullStr = null;
string emptyStr = String.Empty;

string tempStr = str + nullStr;
// Output of the following line: hello
Console.WriteLine(tempStr);

bool b = (emptyStr == nullStr);
// Output of the following line: False
Console.WriteLine(b);

// The following line creates a new empty string.
string newStr = emptyStr + nullStr;

// Null strings and empty strings behave differently. The following
// two lines display 0.
Console.WriteLine(emptyStr.Length);
Console.WriteLine(newStr.Length);
// The following line raises a NullReferenceException.
//Console.WriteLine(nullStr.Length);

// The null character can be displayed and counted, like other chars.
string s1 = "\x0" + "abc";
string s2 = "abc" + "\x0";
// Output of the following line: * abc*
Console.WriteLine("*" + s1 + "*");
// Output of the following line: *abc *
Console.WriteLine("*" + s2 + "*");
// Output of the following line: 4
Console.WriteLine(s2.Length);

Uso di stringBuilder per la creazione rapida di stringhe

Le operazioni di stringa in .NET sono altamente ottimizzate e nella maggior parte dei casi non influiscono in modo significativo sulle prestazioni. Tuttavia, in alcuni scenari, ad esempio cicli rigidi eseguiti molte centinaia o migliaia di volte, le operazioni sulle stringhe possono incidere sulle prestazioni. La classe StringBuilder crea un buffer di stringhe che offre prestazioni migliori se il programma esegue numerose modifiche di stringhe. La StringBuilder stringa consente anche di riassegnare singoli caratteri, un elemento che il tipo di dati stringa predefinito non supporta. Questo codice, ad esempio, consente di modificare il contenuto di una stringa senza crearne una nuova:

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

In questo esempio viene usato un oggetto StringBuilder per creare una stringa da un set di tipi numerici:

var sb = new StringBuilder();

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

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

Console.WriteLine(sb);  // displays 9123456789

Stringhe, metodi di estensione e LINQ

Poiché il tipo String implementa IEnumerable<T> è possibile usare i metodi di estensione definiti nella classe Enumerable sulle stringhe. Per evitare confusione visiva, questi metodi vengono esclusi da IntelliSense per il String tipo, ma sono comunque disponibili. È anche possibile usare espressioni di query LINQ sulle stringhe. Per altre informazioni, vedere LINQ e stringhe.