O que é Span<T>
você lembra dos tipos por valor?
É um novo tipo por valor no coração do .net que permite a representação continua de espaços de memoria, foi mais ou menos isso que o Stephen Toub disse sobre esse recurso no msdn.
Se você ainda não sabe o que é heap e stack de uma olhadinha aqui
Essa frase simples significa;
- é um tipo nativo que não vai ser gerenciado
- é um tipo que fica alocado na Stack
- tem alta performance
- evita o uso de código “unsafe”.
Pense nisso como ter um array para acessar a memória bruta. Vamos fazer um exemplo simples com um array de bytes para entender como acessar a memoria.
var arr = new byte[10];
Span<byte> bytes = arr;
bytes[0] = 42;
Console.WriteLine($"arr:{arr[0]},bytes:{bytes[0]}");
Agora vamos pegar um parte do array e manipula-lo
Span<byte> slices = bytes.Slice(4,3);
slices[0] = 43;
Console.WriteLine($"arr:{arr[4]},bytes:{bytes[4]}");
Agora quando manipulamos um string podemos entender um pouco por que esse recurso é tão bom para saúde das nossas aplicações.
string teste = "WiL171";
teste = teste.Substring(3);
int num = int.Parse(teste);
Console.WriteLine(num);
Com o Span fica assim;
string teste = "WiL171";
ReadOnlySpan<char> s = teste.AsSpan();
s = s.Slice(3);
int num = int.Parse(s);
Console.WriteLine(num);
mas os caras ainda deram uma melhorada e .net core a estrutura ficou assim;
Outros exemplos que podem melhorar o uso de memoria.
Isso;
public static bool ContainsCapitalLetters(string s)
{
for (int i = 0; i < s.Length; i++)
{
if (char.IsUpper(s[i]))
return true;
}
return false;
}
Pra isso;
public static bool ContainsCapitalLetters(ReadOnlySpan<char> s)
{
for (int i = 0; i < s.Length; i++)
{
if (char.IsUpper(s[i]))
return true;
}
return false;
}
ou isso;
public static int Sum(int[] a)
{
int sum = 0;
for (int i = 0; i < a.Length; i++)
{
sum += a[i];
}
return sum;
}
para isso;
public static int Sum(ReadOnlySpan<int> a)
{
int sum = 0;
for (int i = 0; i < a.Length; i++)
{
sum += a[i];
}
return sum;
}
Observe que sempre que vamos usar o span<T> temos esse cara ReadOnlySpan para nos auxiliar, ele tipa uma variável com uma estrutura que nunca vai ser alocada na HEAP e para isso existem muitas restrições quanto ao uso desses tipos.
Por Exemplo, não podemos fazer boxing com eles , não podem ser usados em tipos dinâmicos, nem em expressões lambdas, não podemos usa-los em interfaces, tudo isso para garantir que ele nunca escape para a HEAP.