saverioriotto.it

.NET 8: scopri le nuove funzionalità

Sembra ieri che ci stavamo appassionando a .NET 7, ma stiamo già parlando di .NET 8! Microsoft ha già rilasciato 5 Preview. Vediamo in questo articolo le ultime migliorie e funzionalità aggiunte in questa versione.

.NET 8: scopri le nuove funzionalità

dotnet publish e dotnet pack

Microsoft ha appena rilasciato una nuova funzionalità per i comandi dotnet publish e dotnet pack che rende ancora più semplice la generazione del codice pronto per la produzione.

In precedenza, questi comandi producevano risorse di Debug per impostazione predefinita, il che poteva essere un po' una seccatura se si desiderava produrre nuove build per la produzione. Ma ora, con il nuovo aggiornamento, dotnet publish e dotnet pack produci Release di produzione per impostazione predefinita, il che significa che puoi rapidamente produrre codice pronto per la produzione senza ulteriori passaggi.

Se invece hai bisogno di produrre una Release con supporto di Debug è possibile farlo impostando la proprietà PublishRelease a false;

Come funzionano dotnet publish e dotnet pack?

Innanzitutto, creiamo una nuova applicazione console utilizzando il comando dotnet new. Quindi, costruiamo il progetto utilizzando dotnet build e diamo un'occhiata all'output. In questo caso, l'output sarà in modalità Debug, poiché questo è il comportamento predefinito di dotnet build.

Successivamente, eseguiamo il comando dotnet publish per produrre il codice pronto per la produzione. Con il nuovo aggiornamento, questo comando produrrà Release di produzione per impostazione predefinita. Possiamo vedere le Release pronte nella directory /app/bin/Release/net8.0.

Infine, supponiamo di dover produrre risorse di Debug. Possiamo farlo eseguendo nuovamente il comando dotnet publish, ma questa volta imposteremo la proprietà PublishRelease su false. Questo produrrà risorse di Debug invece di risorse di Release, che troveremo nella directory /app/bin/Debug/net8.0.

Con questa nuova funzionalità, ora è più facile che mai produrre codice pronto per la produzione utilizzando i comandi dotnet publish e dotnet pack.

Miglioramenti nella serializzazione System.Text.Json

In .NET 8 è incorporata la libreria System.Text.Json che fornisce funzionalità di serializzazione e deserializzazione JSON. Consente agli sviluppatori di convertire oggetti .NET in dati JSON e viceversa.

In questa versione System.Text.Json, la funzionalità di serializzazione e deserializzazione, è stata migliorata in diversi aspetti.

Un'altra serie di miglioramenti inclusi in questa anteprima riguarda il generatore dei sorgenti quando viene usato con ASP.NET Core nelle app AOT native, rendendolo più affidabile e veloce.

Inoltre, il generatore di sorgenti supporterà .NET 8 nei tipi di serializzazione con required e init properties, che erano già supportati nella serializzazione basata sulle reflection.

E’ anche possibile personalizzare la serializzazione per i membri che non sono presenti nel payload JSON.

Infine, le proprietà nelle gerarchie di interfaccia ora possono essere serializzate, incluse quelle sia dell'interfaccia immediatamente implementata che della sua interfaccia di base. Vediamolo in un esempio:

IDerived value = new DerivedImplement { Base = 0, Derived =1 };
JsonSerializer.Serialize(value); // {"Base":0,"Derived":1}

public interface IBase
{
    public int Base { get; set; }
}

public interface IDerived : IBase
{
    public int Derived { get; set; }
}

public class DerivedImplement : IDerived
{
    public int Base { get; set; }
    public int Derived { get; set; }
}

E' stato ampliato JsonNamingPolicy per includere i criteri di denominazione in snake_case e kebab-case per le conversioni dei nomi delle proprietà. Queste nuove politiche possono essere utilizzate allo stesso modo della politica JsonNamingPolicy.CamelCase.

var options = new JsonSerializerOptions { PropertyNamingPolicy = JsonNamingPolicy.SnakeCaseLower };
JsonSerializer.Serialize(new { PropertyName = "value" }, options); // { "property_name" : "value" }

Il metodo JsonSerializerOptions.MakeReadOnly() ti dà il controllo esplicito su quando un'istanza JsonSerializerOptions è bloccata. Puoi anche verificare se è di sola lettura con la proprietà IsReadOnly.

GetItems()

Il metodo GetItems() è una nuova funzionalità di .NET 8 che consente di selezionare in modo casuale un numero specifico di elementi da un determinato set di elementi.

Questo può essere utile nei giochi, nelle simulazioni e in altre applicazioni in cui si desidera la casualità. Il metodo è disponibile in entrambi System.Random e System.Security.Cryptography.RandomNumberGenerator.

In questo esempio, abbiamo un array di oggetti City e usiamo il metodo GetItems() per selezionare casualmente 3 città dall'array:

private static ReadOnlySpan s_allCities = new[]
{
    new City("New York", "USA"),
    new City("London", "UK"),
    new City("Paris", "France"),
    new City("Tokyo", "Japan"),
    new City("Sydney", "Australia"),
    
};

...

City[] selectedCities = Random.Shared.GetItems(s_allCities, 3);
foreach (City city in selectedCities)
{
    Console.WriteLine(city.Name + ", " + city.Country);
}
// Output:
// Paris, France
// Tokyo, Japan
// Sydney, Australia

Quindi scorriamo le città selezionate e stampiamo il loro nome e nazione sulla console. L'output sarà diverso ogni volta che eseguiamo il programma, poiché le città vengono selezionate in modo casuale.

Shuffle()

Il metodo Shuffle() è un'altra nuova funzionalità di .NET 8 che consente di rendere casuale l'ordine degli elementi in un intervallo.

Questo è importante nelle istanze di machine learning quando si desidera eliminare l'ordine dei dati di addestramento.

Ecco un esempio che mostra come utilizzare Shuffle() con un array di oggetti TestType:

TestType[] trainingData = LoadTrainingData();
Random.Shared.Shuffle(trainingData);

IDataView sourceData = mlContext.Data.LoadFromEnumerable(trainingData);

DataOperationsCatalog.TrainTestData split = mlContext.Data.TrainTestSplit(sourceData);
model = chain.Fit(split.TrainSet);

IDataView predictions = model.Transform(split.TestSet);
// …

In questo esempio, carichiamo alcuni dati di addestramento in un array di oggetti TestType e usiamo Random.Shared per mescolare l'ordine degli elementi.

Quindi carichiamo i dati mescolati in un oggetto IDataView, dividiamo i dati in set di addestramento e test e utilizziamo i dati di addestramento mescolati per addestrare un modello di machine learning. Infine, utilizziamo il modello addestrato per fare previsioni sul set di test.

Miglioramenti delle prestazioni

.NET 8 introduce diversi nuovi tipi incentrati sul miglioramento delle prestazioni delle app. Questi nuovi tipi sono:

Il namespace System.Collections.Frozen include due tipi di raccolta FrozenDictionary<TKey,TValue> e FrozenSet. Questi tipi non consentono alcuna modifica a chiavi e valori una volta creata una raccolta, il che consente operazioni di lettura più veloci come TryGetValue(). Sono particolarmente utili per le raccolte popolate al primo utilizzo e poi persistenti per la durata di un servizio di lunga durata.

Il tipo System.Text.CompositeFormat è utile per ottimizzare le stringhe di formato che non sono note in fase di compilazione. Un po' di tempo in più viene speso in anticipo per eseguire lavori come l'analisi della stringa, ma evita che il lavoro venga svolto ad ogni utilizzo.

Il tipo System.Buffers.IndexOfAnyValues è progettato per essere passato a metodi che cercano la prima occorrenza di qualsiasi valore nella raccolta passata. .NET 8 aggiunge nuovi overload di metodi come String.IndexOfAny e MemoryExtensions.IndexOfAny che accettano un'istanza del nuovo tipo.

Compilazione nativa anticipata (AOT)

.NET 8 apporta miglioramenti alla funzionalità di compilazione nativa anticipata (AOT) introdotta per la prima volta in .NET 7. La pubblicazione di un'applicazione come AOT nativo genera una versione autonoma dell'app che non richiede un runtime ma tutto è incluso in un unico file.

Oltre al supporto esistente per varie piattaforme, .NET 8 include ora il supporto per le architetture x64 e Arm64 su macOS. Ciò significa che gli sviluppatori possono ora pubblicare le loro app .NET come AOT nativo per i sistemi macOS.

Gli ultimi miglioramenti alle app AOT native su sistemi Linux hanno portato a dimensioni delle applicazioni notevolmente ridotte.

Secondo test recenti, le app AOT native create con .NET 8 Preview 1 ora occupano fino al 50% di spazio in meno rispetto a quelle create con .NET 7.

SO .NET 7 .NET 8
Linux x64 (con -p:StripSymbols=true) 3,76MB

1,84MB

Windows 2,85MB

1,77 MB

Questi miglioramenti nell'AOT nativo possono aiutare gli sviluppatori .NET a creare app più piccole, più veloci ed efficienti che vengono eseguite su un'ampia gamma di piattaforme senza richiedere dipendenze esterne.

Generazione del codice

.NET 8 ha anche alcuni miglioramenti nella generazione del codice e nella compilazione JIT (Just-In-Time) che migliorano le prestazioni e l'efficienza:

 - Miglioramenti delle prestazioni dell'architettura Arm64.
 - Miglioramenti SIMD (Single Instruction Multiple Data) per una migliore vettorizzazione e parallelizzazione delle operazioni.
 - Miglioramenti nativi del cloud per migliori prestazioni in ambienti containerizzati.
 - Miglioramenti dell'ottimizzazione guidata dal profilo (PGO) che consentono migliori ottimizzazioni in base ai modelli di utilizzo dell'applicazione.
 - Supporto per le estensioni ISA AVX-512 per operazioni in virgola mobile più efficienti sulle moderne CPU.
 - Miglioramenti del throughput JIT (Just-In-Time) per una generazione più rapida del codice.
 - Ottimizzazioni generali che migliorano le prestazioni dei blocchi di codice utilizzati di frequente (Loop).

Questi miglioramenti aiutano gli sviluppatori a ottimizzare le prestazioni delle proprie applicazioni .NET e a ridurre l'utilizzo delle risorse negli ambienti nativi del cloud.

Immagini .NET container

.NET 8 apporta anche alcune modifiche al modo in cui funzionano le immagini del container .NET. Innanzitutto, Debian 12 (Bookworm) è ora la distribuzione Linux predefinita nelle immagini del container.

Inoltre, le immagini includono un utente non-root. Per eseguire il container come non-root, aggiungi la riga USER alla fine del tuo Dockerfile o runAsUser nei tuoi manifest Kubernetes.

Anche la porta predefinita è cambiata da 80 a 8080 ed è disponibile una nuova variabile di ambiente per semplificare la modifica delle porte: ASPNETCORE_HTTP_PORTS

Per eseguire il pull di .NET 8 Preview SDK, puoi utilizzare il seguente tag che include il suffisso -preview nel nome del tag per le immagini del container di preview:

docker run --rm -it mcr.microsoft.com/dotnet/sdk:8.0-preview

Il suffisso -preview non verrà più utilizzato per le release candidate (RC). Inoltre, gli sviluppatori possono utilizzare immagini Ubuntu cesellate con .NET 8 che offrono una superficie di attacco più piccola, nessun gestore di pacchetti o shell e funzionalità non-root. Queste immagini sono ideali per gli sviluppatori che cercano i vantaggi dell'elaborazione in stile appliance.

Conclusione

Se sei curioso delle nuove funzionalità o vuoi vedere come si comporta la tua applicazione quando usi la versione .NET 8 Preview, ci sono solo due passaggi per farlo funzionare. Innanzitutto, scarica e installa .NET 8 SDK dal sito Web di .NET. Successivamente, devi modificare il framework di destinazione dei tuoi file di progetto in net8.0. Buona programmazione!




Commenti
* Obbligatorio