Hoje vamos apresentar o recurso Span<T> da linguagem C#. |
O Span<T> é um novo tipo de valor na plataforma .NET que permite reduzir a alocação de memória.
Este recurso permite o gerenciamento fortemente tipado da memória contígua, independentemente de como ela foi alocada. Isso facilita a manutenção do código e melhora muito o desempenho dos aplicativos, reduzindo o número de alocações e cópias de memória necessárias. E ele faz isso oferecendo acesso seguro com características de desempenho semelhantes às das matrizes.
Uma struct Span<T> representa uma região contígua de memória arbitrária, e, uma instância de Span<T> é geralmente usada para manter os elementos de uma matriz ou uma parte de uma matriz. Ao contrário de uma matriz, no entanto, uma instância de Span<T> pode apontar para memória gerenciada, memória nativa ou memória gerenciada na pilha.
Dessa forma a utilidade em usar este recurso esta em podermos simplesmente fatiar um pedaço de memória existente e gerenciá-lo, sem ter que copiá-lo e alocar uma nova memória.
Podemos usar Span com:
A seguir temos uma lista dos tipos que podemos converter para Span<T> :
E usando ReadOnlySpan<T> podemos converter os seguintes tipos :
Principais propriedades :
Principais métodos :
Exemplos de código usando Span<T>
Na verdade Span<T> é uma estrutura de referência que contém um ponteiro para a memória e o comprimento do intervalo.
Exemplo a seguir estamos criando um array com 10 posições (0 a 9) preenchidos com o valor 0.
A seguir convertemos o array para Span<byte> e estamos usando o método Slice para fatiar um intervalo que inicia na posição 5 com tamanho 2.
Depois atribuímos valores aos índices 0 e 1 da fatia e fazemos algumas comparações:
static void Main(string[] args) { Console.WriteLine("Tecle algo para iniciar"); Console.ReadKey();
var vetor = new byte[10];
//define uma fatia do intervalo atual
//atribui valores às fatias
if( 42 ==
bytesFatiados[0])
if( 43.Equals(bytesFatiados[1]))
if (vetor[5].Equals(bytesFatiados[0]))
if (vetor[6].Equals(bytesFatiados[1]))
// lança um IndexOutOfRangeException
if(vetor[2].Equals(bytes[2]))
if (45.Equals(vetor[2]))
Console.ReadKey(); |
Executando o projeto teremos o resultado a seguir:
A seguir veremos um exemplo onde vamos criar um novo Span e copiar elementos de um Span para outro.
static void Main(string[] args)
{
Console.WriteLine("Tecle algo para iniciar");
Console.ReadKey();
int[] arr = { 1, 2, 3, 4, 5 };
Span<int> span = arr.AsSpan();
var destino = new Span<int>(new int[arr.Length]);
span.CopyTo(destino);
span.Clear();
Console.WriteLine("Array:");
foreach (var i in arr)
{
Console.WriteLine(i);
}
Console.WriteLine("Span:");
foreach (var i in span)
{
Console.WriteLine(i);
}
Console.WriteLine("Span de destino:");
foreach (var i in destino)
{
Console.WriteLine(i);
}
Console.ReadKey();
}
|
Neste exemplo usamos o método de extensão AsSpan() para converter um array para um Span e a seguir usamos o método CopyTo para copiar o conteúdo de um Span para outro. Depois limpamos o Span usando o método Clear() e exibimos os elementos.
Resultado:
Agora você tem que considerar que como o
Span é na verdade uma struct e não herda de
IEnumerable, não podemos usar LINQ contra ele. Este é um grande ponto negativo
quando comparado às coleções C#.
Outro detalhe é que o Span também possui um número limitado de métodos
disponíveis. É muito útil para economizar memória, mas em relação à manipulação
de dados para os quais aponta, não podemos fazer muita coisa.
Pegue o projeto aqui: CShp_Span1.zip
"Os que confiam no SENHOR serão como
o monte de Sião, que não se abala, mas permanece para sempre."
Salmos 125:1
Referências:
ADO .NET - Acesso Assíncrono aos dados
C# - Programação Funcional - Exemplos
C# - Coleções Imutáveis
C# 9.0 - Apresentando Records - Macoratti.net
C# - Os 10 Erros mais comuns dos iniciantes
C# - Otimizando o código