Nota
L'accesso a questa pagina richiede l'autorizzazione. È possibile provare ad accedere o modificare le directory.
L'accesso a questa pagina richiede l'autorizzazione. È possibile provare a modificare le directory.
C# include molti tipi di riferimento predefiniti. Questi tipi includono parole chiave o operatori che sono sinonimi di un tipo nella libreria .NET.
Il riferimento al linguaggio C# documenta la versione rilasciata più di recente del linguaggio C#. Contiene anche la documentazione iniziale per le funzionalità nelle anteprime pubbliche per la versione futura del linguaggio.
La documentazione identifica tutte le funzionalità introdotte nelle ultime tre versioni della lingua o nelle anteprime pubbliche correnti.
Suggerimento
Per trovare quando una funzionalità è stata introdotta per la prima volta in C#, vedere l'articolo sulla cronologia delle versioni del linguaggio C#.
Tipo di oggetto
Il tipo object è un alias per System.Object in .NET. Nel sistema di tipi unificato di C#, tutti i tipi, predefiniti e definiti dall'utente, i tipi riferimento e i tipi valore ereditano direttamente o indirettamente da System.Object. Assegnare valori di qualsiasi tipo (ad eccezione ref structdi , vedere ref struct) alle variabili di tipo object. È possibile assegnare il valore letterale null a qualsiasi object variabile come valore predefinito. Quando si converte una variabile di tipo valore in object, il valore viene boxed. Quando si converte una variabile di tipo object in un tipo valore, il valore viene deboxed. Per altre informazioni, vedere Boxing e unboxing.
Tipo di stringa
Il tipo string rappresenta una sequenza di zero o più caratteri Unicode. In .NET string è un alias per System.String.
Anche se string è un tipo riferimento, gli operatori == di uguaglianza e != confrontano i valori degli string oggetti, non i riferimenti. L'uguaglianza basata su valori consente di verificare l'uguaglianza di stringhe più intuitiva. Ad esempio:
string a = "hello";
string b = "h";
// Append to contents of 'b'.
b += "ello";
Console.WriteLine(a == b);
Console.WriteLine(object.ReferenceEquals(a, b));
Nell'esempio precedente viene visualizzato "True" e quindi "False" perché il contenuto delle stringhe è equivalente, ma a non b si riferisce alla stessa istanza di stringa.
L'operatore + concatena le stringhe:
string a = "good " + "morning";
Il codice precedente crea un oggetto stringa che contiene "buongiorno".
Le stringhe non sono modificabili : non è possibile modificare il contenuto di un oggetto stringa dopo averlo creato. Ad esempio, quando si scrive questo codice, il compilatore crea effettivamente un nuovo oggetto stringa per contenere la nuova sequenza di caratteri e assegna tale nuovo oggetto a b. La memoria allocata per b (quando contiene la stringa "h") è quindi idonea per l'operazione di Garbage Collection.
string b = "h";
b += "ello";
È possibile usare l'operatore per l'accesso [] in sola lettura a singoli caratteri di una stringa. I valori di indice validi iniziano a 0 e devono essere minori della lunghezza della stringa:
string str = "test";
char x = str[2]; // x = 's';
In modo simile, è possibile usare l'operatore per eseguire l'iterazione [] su ogni carattere in una stringa:
string str = "test";
for (int i = 0; i < str.Length; i++)
{
Console.Write(str[i] + " ");
}
// Output: t e s t
Valori letterali di stringa
I valori letterali stringa sono di tipo string e sono disponibili in tre forme: raw, quoted e verbatim.
I valori letterali stringa non elaborati contengono testo arbitrario senza richiedere sequenze di escape. I valori letterali stringa non elaborati possono includere spazi vuoti e nuove righe, virgolette incorporate e altri caratteri speciali. I valori letterali stringa non elaborati sono racchiusi tra tre virgolette doppie (""):
"""
This is a multi-line
string literal with the second line indented.
"""
È anche possibile includere una sequenza di tre (o più) caratteri virgolette doppie. Se il testo richiede una sequenza incorporata di virgolette, iniziare e terminare il valore letterale stringa non elaborato con più virgolette, in base alle esigenze:
"""""
This raw string literal has four """", count them: """" four!
embedded quote characters in a sequence. That's why it starts and ends
with five double quotes.
You could extend this example with as many embedded quotes as needed for your text.
"""""
I valori letterali stringa non elaborati hanno in genere le sequenze di virgolette iniziale e finale su righe separate dal testo incorporato. I valori letterali stringa non elaborati su più righe supportano stringhe che sono stesse stringhe tra virgolette:
var message = """
"This is a very important message."
""";
Console.WriteLine(message);
// output: "This is a very important message."
Quando le virgolette iniziali e finali si trovano su righe separate, le nuove righe che seguono l'offerta di apertura e le virgolette precedenti non vengono incluse nel contenuto finale. La sequenza di virgolette di chiusura determina la colonna più a sinistra per il valore letterale stringa. È possibile impostare un rientro di un valore letterale stringa non elaborato in modo che corrisponda al formato di codice complessivo:
var message = """
"This is a very important message."
""";
Console.WriteLine(message);
// output: "This is a very important message."
// The leftmost whitespace is not part of the raw string literal
Le colonne a destra della sequenza di virgolette finali vengono mantenute. Questo comportamento abilita le stringhe non elaborate per i formati di dati, ad esempio JSON, YAML o XML, come illustrato nell'esempio seguente:
var json= """
{
"prop": 0
}
""";
Suggerimento
Visual Studio e C# Dev Kit forniscono alcune funzionalità di convalida e di evidenziazione della sintassi quando i valori letterali stringa non elaborati contengono dati JSON o espressioni regolari.
Gli strumenti analizzano il testo. Se gli strumenti hanno la certezza che il testo rappresenta JSON o un'espressione regolare, l'editor fornisce la colorazione della sintassi.
È possibile migliorare l'esperienza aggiungendo un commento sopra la dichiarazione che indica il formato:
-
// lang=jsonindica che il valore letterale stringa non elaborato rappresenta i dati JSON. -
// lang=regexindica che il valore letterale stringa non elaborato rappresenta un'espressione regolare.
Quando un valore letterale stringa non elaborato viene usato come argomento in cui il parametro usa per System.Diagnostics.CodeAnalysis.StringSyntaxAttribute indicare un formato, questi strumenti convalidano il valore letterale stringa non elaborato per alcuni dei tipi di formato. Sono supportati sia JSON che regex.
Per alcuni formati, il commento o l'attributo abilita i suggerimenti di codice offrono correzioni per i valori letterali stringa in base al formato.
Il compilatore restituisce un errore se una delle righe di testo si estende a sinistra della sequenza di virgolette di chiusura. Le sequenze di virgolette di apertura e di chiusura possono trovarsi sulla stessa riga, a condizione che il valore stringa letterale non inizi né finisca con un carattere di virgolette:
var shortText = """He said "hello!" this morning.""";
È possibile combinare valori letterali stringa non elaborati con l'interpolazione di stringhe per includere caratteri virgolette e parentesi graffe nella stringa di output.
I valori letterali della stringa tra virgolette sono racchiusi in virgolette doppie ("):
"good morning" // a string literal
I valori letterali della stringa possono contenere qualsiasi carattere letterale. Sono incluse le sequenze di escape. L'esempio seguente usa una sequenza di escape \\ per la barra rovesciata, \u0066 per la lettera f e \n per la nuova riga.
string a = "\\\u0066\n F";
Console.WriteLine(a);
// Output:
// \f
// F
Nota
Il codice di escape \udddd (dove dddd è un numero a quattro cifre) rappresenta il carattere Unicode U+dddd. Vengono riconosciuti anche i codici di escape Unicode a otto cifre: \Udddddddd.
I valori letterali della stringa verbatim iniziano con @ e sono anche racchiusi tra virgolette doppie. Ad esempio:
@"good morning" // a string literal
Il vantaggio delle stringhe verbatim è che le sequenze di escape non vengono elaborate, semplificando la scrittura. Ad esempio, il testo seguente corrisponde a un nome file di Windows completo:
@"c:\Docs\Source\a.txt" // rather than "c:\\Docs\\Source\\a.txt"
Per includere una virgoletta doppia in una stringa con @, raddoppiarla:
@"""Ahoy!"" cried the captain." // "Ahoy!" cried the captain.
Valori letterali stringa UTF-8
.NET archivia le stringhe usando la codifica UTF-16. UTF-8 è lo standard per i protocolli Web e altre librerie importanti. È possibile aggiungere il u8 suffisso a un valore letterale stringa per specificare la codifica UTF-8. Il compilatore archivia i valori letterali UTF-8 come ReadOnlySpan<byte> oggetti. L'uso di un valore letterale stringa UTF-8 crea una dichiarazione più chiara rispetto alla dichiarazione equivalente System.ReadOnlySpan<T>, come illustrato nel codice seguente:
ReadOnlySpan<byte> AuthWithTrailingSpace = new byte[] { 0x41, 0x55, 0x54, 0x48, 0x20 };
ReadOnlySpan<byte> AuthStringLiteral = "AUTH "u8;
Per archiviare un valore letterale stringa UTF-8 come matrice, usare ReadOnlySpan<T>.ToArray() per copiare i byte contenenti il valore letterale nella matrice modificabile:
byte[] AuthStringLiteral = "AUTH "u8.ToArray();
I valori letterali stringa UTF-8 non sono costanti in fase di compilazione; sono costanti di runtime. Pertanto, non possono essere usati come valore predefinito per un parametro facoltativo. Non è possibile combinare valori letterali stringa UTF-8 con interpolazione di stringhe. Non è possibile usare il token $ e il suffisso u8 nella stessa espressione stringa.
Tipo di delegato
La dichiarazione di un tipo delegato è simile alla firma di un metodo. Ha un valore restituito e una serie di parametri di qualsiasi tipo:
public delegate void MessageDelegate(string message);
public delegate int AnotherDelegate(MyType m, long num);
In .NET i tipi System.Action e System.Func offrono definizioni generiche per molti delegati comuni. Probabilmente non è necessario definire nuovi tipi di delegato. È possibile eventualmente creare istanze dei tipi generici disponibili.
Un delegate è un tipo di riferimento predefinito che è possibile usare per incapsulare un metodo denominato o anonimo. I delegati sono simili ai puntatori a funzioni in C++, ma sono indipendenti dai tipi e protetti. Per le applicazioni dei delegati, vedere Delegati e Delegati generici. I delegati sono la base degli eventi. È possibile creare un'istanza di un delegato associandolo a un metodo denominato o anonimo.
È necessario creare un'istanza del delegato con un metodo o un'espressione lambda con un tipo restituito e parametri di input compatibili. Per altre informazioni sul grado di varianza consentito nella firma del metodo, vedere Varianza nei delegati. Per l'uso con metodi anonimi, dichiarare il delegato e il codice da associare insieme.
La combinazione o la rimozione del delegato non riesce con un'eccezione di runtime quando i tipi delegati coinvolti in fase di esecuzione sono diversi a causa della conversione di varianti. L'esempio seguente illustra una situazione che ha esito negativo:
Action<string> stringAction = str => {};
Action<object> objectAction = obj => {};
// Valid due to implicit reference conversion of
// objectAction to Action<string>, but might fail
// at run time.
Action<string> combination = stringAction + objectAction;
È possibile creare un delegato con il tipo di runtime corretto creando un nuovo oggetto delegato. Nell'esempio seguente viene illustrato come applicare questa soluzione alternativa all'esempio precedente.
Action<string> stringAction = str => {};
Action<object> objectAction = obj => {};
// Creates a new delegate instance with a runtime type of Action<string>.
Action<string> wrappedObjectAction = new Action<string>(objectAction);
// The two Action<string> delegate instances can now be combined.
Action<string> combination = stringAction + wrappedObjectAction;
È possibile dichiarare puntatori a funzione, che usano una sintassi simile. Un puntatore a funzione usa l'istruzione calli anziché creare un'istanza di un tipo delegato e chiamare il metodo virtuale Invoke.
Tipo dinamico
Il dynamic tipo indica che la variabile e fa riferimento ai relativi membri ignora il controllo dei tipi in fase di compilazione. Queste operazioni vengono risolte in fase di esecuzione. Il tipo dynamic semplifica l'accesso alle API COM, ad esempio le API di automazione di Office, alle API dinamiche, ad esempio le librerie di IronPython, e al modello DOM (Document Object Model) HTML.
Il tipo dynamic si comporta come tipo object nella maggior parte dei casi. In particolare, qualsiasi espressione non null può essere convertita nel tipo dynamic. Il dynamic tipo differisce da in object quanto il compilatore non risolve o non risolve le operazioni di controllo del tipo che contengono espressioni di tipo dynamic. Il compilatore raggruppa le informazioni sull'operazione e tali informazioni successivamente vengono usate per valutare l'operazione in fase di esecuzione. Come parte del processo, le variabili di tipo dynamic vengono compilate in variabili di tipo object. Di conseguenza, il tipo dynamic esiste solo in fase di compilazione, non in fase di esecuzione.
L'esempio seguente contrasta una variabile di tipo dynamic con una variabile di tipo object. Per verificare il tipo di ogni variabile in fase di compilazione, posizionare il puntatore del mouse su dyn o obj nelle istruzioni WriteLine. Copiare il codice seguente in un editor in cui IntelliSense è disponibile. IntelliSense visualizza dynamic per dyn e object per obj.
class Program
{
static void Main(string[] args)
{
dynamic dyn = 1;
object obj = 1;
// Rest the mouse pointer over dyn and obj to see their
// types at compile time.
System.Console.WriteLine(dyn.GetType());
System.Console.WriteLine(obj.GetType());
}
}
Le istruzioni WriteLine visualizzano i tipi in fase di esecuzione di dyn e obj. A questo punto, entrambe hanno lo stesso tipo, un numero intero. Viene prodotto l'output seguente:
System.Int32
System.Int32
Per vedere la differenza tra dyn e obj in fase di compilazione, aggiungere le due righe seguenti tra le dichiarazioni e le istruzioni WriteLine dell'esempio precedente.
dyn = dyn + 3;
obj = obj + 3;
Viene segnalato un errore del compilatore per il tentativo di aggiunta di un numero intero e di un oggetto nell'espressione obj + 3. Tuttavia non vengono segnalati errori per dyn + 3. L'espressione che contiene dyn non viene controllata in fase di compilazione perché il tipo di dyn è dynamic.
Nell'esempio seguente viene usato dynamic in diverse dichiarazioni. Il metodo Main confronta anche il controllo dei tipi in fase di compilazione con il controllo dei tipi in fase di esecuzione.
using System;
namespace DynamicExamples
{
class Program
{
static void Main(string[] args)
{
ExampleClass ec = new ExampleClass();
Console.WriteLine(ec.ExampleMethod(10));
Console.WriteLine(ec.ExampleMethod("value"));
// The following line causes a compiler error because ExampleMethod
// takes only one argument.
//Console.WriteLine(ec.ExampleMethod(10, 4));
dynamic dynamic_ec = new ExampleClass();
Console.WriteLine(dynamic_ec.ExampleMethod(10));
// Because dynamic_ec is dynamic, the following call to ExampleMethod
// with two arguments does not produce an error at compile time.
// However, it does cause a run-time error.
//Console.WriteLine(dynamic_ec.ExampleMethod(10, 4));
}
}
class ExampleClass
{
static dynamic _field;
dynamic Prop { get; set; }
public dynamic ExampleMethod(dynamic d)
{
dynamic local = "Local variable";
int two = 2;
if (d is int)
{
return local;
}
else
{
return two;
}
}
}
}
// Results:
// Local variable
// 2
// Local variable
Specifiche del linguaggio C#
Per altre informazioni, vedere le sezioni seguenti delle specifiche del linguaggio C#:
- §8.2.3 Tipo di oggetto
- §8.2.4 Tipo dinamico
- §8.2.5 Tipo stringa
- §8.2.8 Tipi delegati
- Valori letterali stringa non elaborati
- Valori letterali stringa UTF-8
Vedi anche
- Parole chiave di C#
- Eventi
- Uso del tipo dinamico
- Procedure consigliate per l'uso delle stringhe
- Creazione di nuove stringhe
- Operatori di cast e di test del tipo
- Procedura: Eseguire il cast sicuro con i criteri di ricerca e gli operatori as e is
- Procedura dettagliata: Creazione e utilizzo di oggetti dinamici
- System.Object
- System.String
- System.Dynamic.DynamicObject