Novità di C# 12
C# 12 include le nuove funzionalità seguenti. È possibile provare queste funzionalità usando la versione più recente Visual Studio 2022 o .NET 8 SDK.
Costruttori Primari - Introdotto in Visual Studio 2022 versione 17.6 Preview 2.
Espressioni di Raccolta - Introdotte in Visual Studio 2022 versione 17.7 Preview 5.
matrici inline - introdotte in Visual Studio 2022 versione 17.7 Preview 3.
Parametri facoltativi nelle espressioni lambda - Introdotto in Visual Studio 2022 versione 17.5 Preview 2.
ref readonly
parametri - Introdotto in Visual Studio 2022 versione 17.8 Preview 2.Alias qualsiasi tipo - Introdotto in Visual Studio 2022 versione 17.6 Preview 3.
attributo sperimentale - Introdotto in Visual Studio 2022 versione 17.7 Preview 3.
Intercettori - funzionalità di anteprima introdotte in Visual Studio 2022 versione 17.7 Preview 3.
C# 12 è supportato in .NET 8. Per ulteriori informazioni, vedere versionamento del linguaggio C#.
È possibile scaricare la versione più recente di .NET 8 SDK dalla pagina di download di .NET . È anche possibile scaricare Visual Studio 2022, che include .NET 8 SDK.
Nota
Microsoft è interessato ai commenti e suggerimenti su queste funzionalità. Se trovi problemi con una di queste nuove funzionalità, crea un nuovo problema nel repository dotnet/roslyn.
Costruttori primari
È ora possibile creare costruttori primari in qualsiasi class
e struct
. I costruttori primari non sono più limitati ai tipi record
. I parametri del costruttore primario sono disponibili per l'intero corpo della classe. Per garantire che tutti i parametri del costruttore primario siano assegnati in modo definitivo, tutti i costruttori dichiarati in modo esplicito devono chiamare il costruttore primario usando this()
sintassi. L'aggiunta di un costruttore primario a un class
impedisce al compilatore di dichiarare un costruttore implicito senza parametri. In un struct
il costruttore implicito senza parametri inizializza tutti i campi, inclusi i parametri del costruttore primario nel modello a 0 bit.
Il compilatore genera proprietà pubbliche per i parametri del costruttore primario solo nei tipi record
, record class
o record struct
. Le classi e gli struct non registrati potrebbero non voler sempre questo comportamento per i parametri del costruttore primario.
Puoi apprendere di più sui costruttori primari nell'esercitazione per che esplora i costruttori primari e nell'articolo sui costruttori di istanze .
Espressioni di raccolta
Le espressioni di raccolta introducono una nuova sintassi terse per creare valori di raccolta comuni. È possibile includere altre raccolte in questi valori usando un elemento spread ..e
.
È possibile creare diversi tipi simili a raccolte senza richiedere supporto BCL esterno. Questi tipi sono:
- Tipi di matrice, ad esempio
int[]
. - System.Span<T> e System.ReadOnlySpan<T>.
- Tipi che supportano gli inizializzatori di raccolta, ad esempio System.Collections.Generic.List<T>.
Negli esempi seguenti vengono illustrati gli usi delle espressioni di raccolta:
// Create an array:
int[] a = [1, 2, 3, 4, 5, 6, 7, 8];
// Create a list:
List<string> b = ["one", "two", "three"];
// Create a span
Span<char> c = ['a', 'b', 'c', 'd', 'e', 'f', 'h', 'i'];
// Create a jagged 2D array:
int[][] twoD = [[1, 2, 3], [4, 5, 6], [7, 8, 9]];
// Create a jagged 2D array from variables:
int[] row0 = [1, 2, 3];
int[] row1 = [4, 5, 6];
int[] row2 = [7, 8, 9];
int[][] twoDFromVariables = [row0, row1, row2];
L'elemento spread, ..e
in un'espressione di raccolta aggiunge tutti gli elementi in tale espressione. L'argomento deve essere un tipo di raccolta. Gli esempi seguenti illustrano il funzionamento dell'elemento spread:
int[] row0 = [1, 2, 3];
int[] row1 = [4, 5, 6];
int[] row2 = [7, 8, 9];
int[] single = [.. row0, .. row1, .. row2];
foreach (var element in single)
{
Console.Write($"{element}, ");
}
// output:
// 1, 2, 3, 4, 5, 6, 7, 8, 9,
L'elemento spread valuta ogni elemento dell'espressione di enumerazione. Ogni elemento è incluso nella raccolta di output.
È possibile usare espressioni di raccolta in qualsiasi punto in cui è necessaria una raccolta di elementi. Possono specificare il valore iniziale per una raccolta o essere passati come argomenti ai metodi che accettano tipi di raccolta. Per saperne di più sulle espressioni di raccolta, consultare l'articolo di riferimento sul linguaggio relativo alle espressioni di raccolta o la specifica della funzionalità .
parametri ref readonly
C# ha aggiunto i parametri in
per consentire di passare riferimenti di sola lettura.
in
parametri consentono sia variabili che valori e possono essere usati senza alcuna annotazione sugli argomenti.
L'aggiunta di parametri di ref readonly
consente maggiore chiarezza per le API che potrebbero usare parametri ref
o parametri in
:
- Le API create prima dell'introduzione di
in
potrebbero usareref
anche se l'argomento non viene modificato. Queste API possono essere aggiornate conref readonly
. Non sarà una modifica che causa un'interruzione per i chiamanti, come se il parametroref
fosse stato modificato inin
. Un esempio è System.Runtime.InteropServices.Marshal.QueryInterface. - Le API che accettano un parametro
in
, ma richiedono logicamente una variabile. Un'espressione di valore non funziona. Un esempio è System.ReadOnlySpan<T>.ReadOnlySpan<T>(T). - API che usano
ref
perché richiedono una variabile, ma non modificano tale variabile. Un esempio è System.Runtime.CompilerServices.Unsafe.IsNullRef.
Per altre informazioni sui parametri di ref readonly
, consultare l'articolo sui modificatori di parametri nella documentazione del linguaggio o la specifica della funzionalità dei parametri ref readonly .
Parametri lambda predefiniti
È ora possibile definire i valori predefiniti per i parametri nelle espressioni lambda. La sintassi e le regole corrispondono all'aggiunta di valori predefiniti per gli argomenti a qualsiasi metodo o funzione locale.
Per altre informazioni sui parametri predefiniti sulle espressioni lambda, vedere l'articolo sulle espressioni lambda .
Alias qualsiasi tipo
È possibile usare la direttiva alias using
per eseguire l'alias di qualsiasi tipo, non solo i tipi nominati. Ciò significa che è possibile creare alias semantici per tipi di tupla, tipi di matrice, tipi di puntatore o altri tipi non sicuri. Per altre informazioni, vedere la specifica di funzionalità . Per una procedura dettagliata di refactoring di esempio, vedere Effettuare il refactoring del codice usando alias qualsiasi tipo nel blog di .NET.
Matrici inline
Le matrici inline vengono usate dal team di runtime e da altri autori di librerie per migliorare le prestazioni nelle app. Le matrici inline consentono a uno sviluppatore di creare una matrice di dimensioni fisse in un tipo di struct
. Uno struct con un buffer inline deve fornire caratteristiche di prestazioni simili a un buffer di dimensioni fisse non sicure. È probabile che non dichiari le tue matrici inline, ma le usi in modo trasparente quando vengono esposte come oggetti System.Span<T> o System.ReadOnlySpan<T> dalle API di runtime.
Un array inline viene dichiarato simile al struct
seguente:
[System.Runtime.CompilerServices.InlineArray(10)]
public struct Buffer
{
private int _element0;
}
Si usano come qualsiasi altro array:
var buffer = new Buffer();
for (int i = 0; i < 10; i++)
{
buffer[i] = i;
}
foreach (var i in buffer)
{
Console.WriteLine(i);
}
La differenza è che il compilatore può sfruttare informazioni note su una matrice inline. Probabilmente utilizzi le matrici inline come qualsiasi altra matrice. Per altre informazioni su come dichiarare matrici inline, vedere le informazioni di riferimento sul linguaggio sui tipi struct
.
Attributo sperimentale
I tipi, i metodi o gli assembly possono essere contrassegnati con il System.Diagnostics.CodeAnalysis.ExperimentalAttribute per indicare una funzionalità sperimentale. Il compilatore genera un avviso se si accede a un metodo o a un tipo annotato con il ExperimentalAttribute. Tutti i tipi inclusi in un assembly contrassegnato con l'attributo Experimental
sono sperimentali. Per altre informazioni, vedere l'articolo sugli attributi generali letti dal compilatoreoppure la specifica di funzionalità .
Intercettori
Avvertimento
Gli intercettori sono una funzionalità sperimentale, disponibile in modalità di anteprima con C# 12. La funzionalità può essere soggetta a modifiche importanti o rimozione in una versione futura. Pertanto, non è consigliabile per le applicazioni di produzione o rilasciate.
Per usare gli intercettori, il progetto utente deve specificare la proprietà <InterceptorsPreviewNamespaces>
. Questo è un elenco di namespace abilitati a contenere intercettori.
Ad esempio: <InterceptorsPreviewNamespaces>$(InterceptorsPreviewNamespaces);Microsoft.AspNetCore.Http.Generated;MyLibrary.Generated</InterceptorsPreviewNamespaces>
Un intercettore è un metodo che può sostituire in modo dichiarativo una chiamata a un metodo intercettabile con una chiamata a se stessa in fase di compilazione. Questa sostituzione avviene con l'intercettore che dichiara le posizioni di origine delle chiamate intercettate. Gli intercettori offrono una funzionalità limitata per modificare la semantica del codice esistente aggiungendo nuovo codice a una compilazione, ad esempio in un generatore di origine.
Si usa un intercettore come parte di un generatore di origine per modificare, anziché aggiungere codice a una compilazione di origine esistente. Il generatore di origine sostituisce le chiamate a un metodo intercettabile con una chiamata al metodo intercettore.
Se si è interessati a sperimentare con gli intercettori, è possibile ottenere altre informazioni leggendo la specifica della funzionalità . Se si usa la funzionalità, assicurarsi di rimanere aggiornati con le modifiche apportate alla specifica della funzionalità per questa funzionalità sperimentale. Se la funzionalità è stata finalizzata, verranno aggiunte altre indicazioni in questo sito.