Condividi tramite


Stringhe e valori letterali stringa

Una stringa è un oggetto di tipo String il cui valore è testo. Internamente, il testo è memorizzato come una collezione sequenziale a sola lettura di oggetti Char. La proprietà Length di una stringa rappresenta il numero di oggetti Char che contiene, 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 C# la parola chiave string è un alias per String; pertanto, String e string sono equivalenti. Usare l'alias fornito string dato che funziona anche senza using System;. La classe String fornisce molti metodi per creare, modificare e confrontare in modo sicuro le stringhe. Inoltre, il linguaggio C# esegue l'overload di alcuni operatori per semplificare le operazioni comuni sulle stringhe. Per altre informazioni sulla parola chiave, vedere stringa. 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 illustrato 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 l'operatore nuovo 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 la cui stringa è di lunghezza zero. La rappresentazione letterale di una stringa di lunghezza zero è "". Inizializzando le stringhe con il valore Empty anziché null, è possibile ridurre le probabilità che si verifichi un NullReferenceException. Usare il metodo IsNullOrEmpty(String) statico per verificare il valore di una stringa prima di provare ad accedervi.

Immutabilità delle stringhe

Gli oggetti stringa sono non modificabili: non possono essere modificati dopo la creazione. Tutti i metodi String e gli operatori C# che sembrano modificare una stringa restituiscono effettivamente i risultati in un nuovo oggetto stringa. Nell'esempio seguente, quando il contenuto di s1 e s2 vengono concatenati per formare una singola stringa, le due stringhe originali non vengono modificate. L'operatore += crea una nuova stringa contenente il contenuto combinato. Tale nuovo oggetto viene assegnato alla variabile s1e l'oggetto originale che era stato assegnato a s1 viene liberato per la raccolta dei rifiuti perché nessun'altra variabile contiene un riferimento ad esso.

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.

Poiché la modifica di una stringa è in realtà 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 continua a puntare all'oggetto originale anziché al nuovo oggetto creato al momento della modifica della stringa. 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.

Letterali di stringa tra virgolette

I valori letterali delle stringhe tra virgolette iniziano 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 . Una stringa letterale 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 stringa verbatim

stringhe letterali verbatim sono più convenienti per le stringhe a più righe, le stringhe che contengono barre rovesciate o virgolette doppie incorporate. Le stringhe verbatim mantengono i caratteri di nuova riga come parte del testo della stringa. Usare le virgolette doppie per incorporare un segno di citazione all'interno di una stringa letterale. L'esempio seguente illustra alcuni usi comuni delle stringhe letterali:

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

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

Letterali di stringa grezza

A partire da C# 11, è possibile usare stringhe letterali grezze per creare più facilmente stringhe multilinea o usare qualsiasi carattere che richiedono sequenze di escape. letterali di stringa grezzi rimuovono la necessità di usare sequenze di escape. Puoi scrivere la stringa, inclusa la formattazione degli spazi bianchi, come desideri che appaia nell'output. Un valore letterale stringa non elaborato:

  • Inizia e termina con una sequenza di almeno tre caratteri virgolette doppie ("""). È possibile usare 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 letterali di stringa grezzi a riga singola richiedono che i caratteri di apertura e chiusura delle virgolette siano sulla stessa riga.
  • I valori letterali stringa non elaborati su più righe richiedono caratteri di virgolette di apertura e chiusura sulla propria riga.
  • Nei valori letterali stringa non elaborati su più righe, qualsiasi spazio vuoto a sinistra delle virgolette di chiusura viene rimosso da tutte le righe del valore letterale stringa non elaborato.
  • Nei letterali di stringa grezzi multilinea, gli spazi bianchi successivi all'apertura delle virgolette sulla stessa riga vengono ignorati.
  • Nei letterali di stringa grezzi su più righe, le righe composte solo da spazi vuoti che seguono le virgolette di apertura sono incluse nel letterale di stringa.

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é le stringhe letterali raw multilinea richiedono la sequenza di virgolette di apertura e chiusura su una propria riga. Il terzo esempio non è valido perché il testo sporge dalla sequenza di virgolette di chiusura.

Quando si genera testo che include caratteri che richiedono sequenze di escape quando si usano valori letterali stringa tra virgolette o valori letterali stringa verbatim, è consigliabile prendere in considerazione valori letterali stringa non elaborati. I letterali di stringhe grezze sono più facili da leggere perché assomigliano di più 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"
  ]
}
""";

Sequenze di escape delle stringhe

Sequenza di escape Nome del personaggio Codifica Unicode
\' Virgolette singole 0x0027
\" Virgolette doppie 0x0022
\\ Barra rovesciata 0x005C
\0 Nullo 0x0000
\a Allerta 0x0007
\b Backspace 0x0008
\e Fuga 0x001B
\f Salto pagina 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", ad eccezione della lunghezza variabile \xH[H][H][H] (intervallo: 0 - FFFF; esempio: \x00E7 o \x0E7 o \xE7 = "ç")

Avvertimento

Quando si usa la sequenza di escape \x e specificando meno di 4 cifre esadecimale, se i caratteri che seguono immediatamente la sequenza di escape sono cifre esadecimale valide (ad esempio 0-9, A-F e a-f), verranno interpretate 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 \xA1A e produrrà "ਚ", ovvero il punto di codice U+0A1A. In questi casi, specificando tutte le 4 cifre esadecimale (ad esempio, \x00A1) si evita qualsiasi possibile interpretazione errata.

Nota

In fase di compilazione, le stringhe verbatim e raw vengono convertite in stringhe normali con tutte le stesse sequenze di escape. Pertanto, se si visualizza una stringa letterale o grezza nella finestra di controllo del debugger, verranno visualizzati i caratteri di escape aggiunti dal compilatore, non la versione letterale o grezza del codice sorgente. Ad esempio, la stringa verbatim @"C:\files.txt" verrà visualizzata nella finestra 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 espressioni interpolate o segnaposto all'interno di parentesi graffe di una stringa. Tutti gli elementi all'interno delle parentesi graffe ({...}) vengono risolti in un valore e vengono forniti come stringa formattata durante l'esecuzione. Esistono due metodi per creare stringhe di formato: interpolazione di stringhe e formattazione composita.

Interpolazione di stringhe

Dichiari stringhe interpolate con il carattere speciale $. Una stringa interpolata include espressioni interpolate tra parentesi graffe. Se sei nuovo all'interpolazione di stringhe, consulta 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 ottiene gli stessi risultati del metodo String.Format, ma migliora la facilità d'uso e la chiarezza in linea.

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.

È possibile usare l'interpolazione di stringhe per inizializzare una stringa costante quando anche tutte le espressioni utilizzate per i segnaposto sono stringhe costanti.

A partire da C# 11, è possibile combinare valori letterali stringa non elaborati con interpolazioni di stringhe. Si inizia e termina 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 il numero di caratteri { e } iniziale e finale di un'interpolazione. Qualsiasi sequenza di meno { o } caratteri viene inclusa nell'output. Nell'esempio seguente viene illustrato come usare questa 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.

Interpolazione di stringhe (verbatim)

C# consente anche l'interpolazione di stringhe verbatim, ad esempio tra più righe, usando la sintassi $@ o @$.

Per interpretare letteralmente le sequenze di escape, usare un valore letterale stringa verbatim. Una stringa verbatim interpolata inizia con il carattere $ seguito dal carattere @. È possibile usare i token di $ e @ in qualsiasi ordine: sia $@"..." che @$"..." sono stringhe verbatim interpolate valide.

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}.");

// Output:
// Jupiter Hammon
//     was an African American poet born in 1711.
// He was first published in 1761
// at the age of 50.

Formattazione composita

Il String.Format utilizza segnaposto tra parentesi graffe per creare una stringa di formato. In questo esempio viene restituito un output simile al metodo di interpolazione di stringhe usato nell'esempio precedente.

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. Utilizzare il metodo Substring per creare una nuova stringa da una parte della stringa originale. È possibile cercare una o più occorrenze di una sottostringa usando il metodo IndexOf. Utilizzare il metodo Replace per sostituire tutte le occorrenze di una sottostringa specificata con una nuova stringa. Analogamente al metodo Substring, 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 usare la notazione di matrice con un valore di indice per acquisire l'accesso in sola lettura ai 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 metodi String non forniscono la funzionalità necessaria per modificare singoli caratteri in una stringa, è possibile usare un oggetto StringBuilder per modificare i singoli caratteri "sul posto" e quindi creare una nuova stringa per archiviare i risultati usando i metodi StringBuilder. Nell'esempio seguente si supponga di dover modificare la stringa originale in modo particolare e quindi archiviare i risultati per un 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 vengono usate spesso in vari scenari di programmazione per rappresentare un campo di testo vuoto. È possibile chiamare metodi su stringhe vuote perché sono oggetti System.String validi. Le stringhe vuote vengono inizializzate nel modo seguente:

string s = String.Empty;

Al contrario, una stringa Null non fa riferimento a un'istanza di un oggetto System.String e qualsiasi tentativo di chiamare un metodo su una stringa Null causa un 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 nulla provoca o non provoca 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, come i cicli stretti che vengono eseguiti molte centinaia o migliaia di volte, le operazioni sulle stringhe possono influire sulle prestazioni. La classe StringBuilder crea un buffer di stringhe che offre prestazioni migliori se il programma esegue molte manipolazioni di stringhe. La stringa StringBuilder consente anche di riassegnare singoli caratteri, un elemento che il tipo di dati stringa predefinito non supporta. Questo codice, ad esempio, modifica il contenuto di una stringa senza creare una nuova stringa:

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 tipo String, ma sono comunque disponibili. È anche possibile usare espressioni di query LINQ sulle stringhe. Per ulteriori informazioni, vedere LINQ e Stringhe.