Con l'introduzione di .NET Core, Microsoft ha messo in discussione l'intero .NET Framework che si è sviluppato negli anni e, grazie ad un nuovo processo di sviluppo, fatto da iterazioni più veloci, il coinvolgimento della community e il confrontarsi con altri prodotti, questo ha portato ad un'estrema ottimizzazione delle architetture e le prestazioni del runtime e delle librerie.
In questo processo si è visto come nel mondo .NET esistono tre modi diversi per allocare la memoria a seconda delle necessità: di stack, nell'heap non gestito, nell'heap gestito. Quest'ultimo è quello che usiamo più abitualmente ed è fatto di oggetti creati con la parola chiave new oppure di array. A seconda del tipo di allocazione, però, dobbiamo scorrere e modificare i byte in modi differenti.
Mediante l'introduzione di un nuovo pacchetto NuGet System.Memory attualmente in prerelease, invece, possiamo ora uniformare l'accesso e ottimizzare l'uso della memoria evitando inutili allocazioni. Installato il pacchetto vengono forniti due tipi ReadOnlySpan<T> e Span<T> rispettivamente per leggere o per leggere e modificare una sequenza. Disponiamo, inoltre, di extension method per agevolarci nelle conversioni, per esempio da una stringa.
// Crea uno span sulla base di una stringa // cioè di un array di char ReadOnlySpan<char> stringaSpan = "Questa è una stringa".AsSpan();
La funzione Slice, tra le più interessanti, restituisce un nuovo ReadOnlySpan<T>, una struct di basso impatto, che si riferisce sempre alla medesima area di memoria o ad un suo sottoinsieme, senza quindi creare nuovi array o nuove stringhe.
// Stampa 6 Console.WriteLine(stringaSpan.Length); // Stampa false Console.WriteLine(stringaSpan.IsEmpty); // Converto in un nuovo array string questaString = new string(questaSpan.ToArray()); Console.WriteLine(questaString);
Partendo da un array o da allocazioni non gestite, possiamo creare uno Span<T> e proseguire quindi a travasi o a manipolazioni.
char[] charArray = "Questa è una stringa".ToCharArray(); // Span dall'array, modifabile Span<char> stringa2Span = new Span<char>(charArray); // Errore a runtime, troppo piccolo "Quella non".AsSpan().CopyTo(stringa2Span.Slice(0, 6)); // Copio in uno spazio sufficiente "quella".AsSpan().CopyTo(stringa2Span.Slice(0, 6)); Span<byte> bytesSpan = stringa2Span.AsBytes(); // Cambio il primo carattere in "Q" maiuscolo. In unicode sono due byte bytesSpan[0] = 81; bytesSpan[1] = 0; // Converto in un array char[] charArray2 = stringa2Span.ToArray(); // Stampa false, viene ottenuta una nuova allocazione Console.WriteLine(Object.ReferenceEquals(charArray, charArray2)); // Stampa "Quella è una stringa" dall'array originale string questaString2 = new string(charArray); Console.WriteLine(questaString2);
Nell'esempio viene mostrato come sia anche possibile passare ad interpretazioni di tipo diverso, pur manipolando sempre la stessa area di memoria.
L'uso di questa struttura, quindi, è l'ideale quando dobbiamo analizzare o manipolare sequenze di aree di memoria. E' prevista anche l'introduzione di un Memory<T>, una sorta di factory per Span<T>, utile per interfacciarsi anche con Stream, ma al momento non risulta ancora disponibile. Per maggiori dettagli rimandiamo alla issue dedicata allo sviluppo.
https://github.com/dotnet/coreclr/issues/5851
Commenti
Per inserire un commento, devi avere un account.
Fai il login e torna a questa pagina, oppure registrati alla nostra community.
Approfondimenti
Utilizzare l'espressione if inline in una pipeline di Azure DevOps
Eseguire una query su SQL Azure tramite un workflow di GitHub
Usare il colore CSS per migliorare lo stile della pagina
Generare HTML a runtime a partire da un componente Razor in ASP.NET Core
Supporto ai tipi DateOnly e TimeOnly in Entity Framework Core
Assegnare un valore di default a un parametro di una lambda in C#
Effettuare il log delle chiamate a function di GPT in ASP.NET Web API
Eseguire query manipolando le liste contenute in un oggetto mappato verso una colonna JSON
Gestire i dati con Azure Cosmos DB Data Explorer
Gestire gli accessi con Token su Azure Container Registry
Supportare il sorting di dati tabellari in Blazor con QuickGrid
Utilizzare il nuovo modello GPT-4o con Azure OpenAI