Observação
O acesso a essa página exige autorização. Você pode tentar entrar ou alterar diretórios.
O acesso a essa página exige autorização. Você pode tentar alterar os diretórios.
A SpanOwner<T> classe é um tipo de buffer somente pilha que aluga buffers de um pool de memória compartilhado. Essencialmente, ele espelha a funcionalidade de MemoryOwner<T>, mas como um tipo ref struct. Essa funcionalidade é particularmente útil para buffers de curta duração que são usados apenas em código síncrono (que não exigem Memory<T> instâncias), bem como código em execução em um loop apertado. A criação SpanOwner<T> de valores não requer alocações de memória.
APIs de Plataforma:
SpanOwner<T>,MemoryOwner<T>
Sintaxe
As mesmas funcionalidades principais de MemoryOwner<T> aplicam-se a este tipo, com a exceção de ser um tipo apenas de structpilha. Ele também não tem a IMemoryOwner<T>interface implementação, bem como a Memory<T> propriedade. A sintaxe é praticamente idêntica à sintaxe usada com MemoryOwner<T>, exceto pelas diferenças mencionadas anteriormente.
Por exemplo, suponha que você tenha um método em que precisa alocar um buffer temporário de um tamanho especificado (vamos chamar esse valor length) e, em seguida, usá-lo para executar algum trabalho. Uma primeira versão ineficiente pode ter essa aparência:
byte[] buffer = new byte[length];
// Use buffer here
Essa versão não é ideal porque aloca um novo buffer sempre que você usa esse código e o joga fora imediatamente. Essa abordagem coloca mais pressão sobre o coletor de lixo. Você pode otimizar o código anterior usando ArrayPool<T>:
// Using directive to access the ArrayPool<T> type
using System.Buffers;
int[] buffer = ArrayPool<int>.Shared.Rent(length);
try
{
// Slice the span, as it might be larger than the requested size
Span<int> span = buffer.AsSpan(0, length);
// Use the span here
}
finally
{
ArrayPool<int>.Shared.Return(buffer);
}
O código anterior aluga um buffer de um pool de matrizes, mas é mais detalhado e propenso a erros. Você precisa ter cuidado com o bloco try/finally para garantir que você sempre devolva o buffer emprestado ao pool. Você pode reescrevê-lo usando o SpanOwner<T> tipo, da seguinte maneira:
// Be sure to include this using at the top of the file:
using Microsoft.Toolkit.HighPerformance.Buffers;
using SpanOwner<int> buffer = SpanOwner<int>.Allocate(length);
Span<int> span = buffer.Span;
// Use the span here, no slicing necessary
A SpanOwner<T> instância aluga internamente uma matriz e cuida de devolvê-la ao pool quando ela sai do escopo. Você também não precisa mais usar um try/finally bloco, pois o compilador C# adiciona isso automaticamente ao expandir essa using instrução. Dessa forma, você pode ver o SpanOwner<T> tipo como um wrapper leve em torno das ArrayPool<T> APIs. Isso os torna mais compactos e fáceis de usar, reduzindo a quantidade de código que você precisa escrever para alugar e descartar corretamente buffers de curta duração. Você pode ver que usar o SpanOwner<T> torna o código mais curto e simples.
Observação
Como este é um tipo somente de pilha, ele se baseia no padrão de IDisposable tipo duck introduzido com C# 8. **
Esse padrão é mostrado no exemplo anterior: o tipo SpanOwner<T> é usado dentro de using bloco, embora não implemente a interface IDisposable e também nunca seja encapsulado. A funcionalidade permanece a mesma: assim que o buffer sai do escopo, ele é automaticamente descartado. As APIs nas SpanOwner<T> dependem desse padrão para um desempenho extra: elas pressupõem que o subjacente buffer nunca seja liberado, contanto que o tipo SpanOwner<T> esteja no escopo. Eles não realizam as verificações adicionais feitas em MemoryOwner<T> para garantir que o buffer ainda esteja disponível antes de retornar uma instância de Memory<T> ou Span<T> dele. Como tal, sempre use esse tipo com um using bloco ou expressão. Não fazer isso faz com que o buffer subjacente não seja retornado ao pool compartilhado. Tecnicamente, você pode obter o mesmo resultado chamando manualmente Dispose no tipo SpanOwner<T> (que não requer C# 8), mas essa abordagem é propensa a erros e, portanto, não é recomendada.
Exemplos
Você pode encontrar mais exemplos nos testes de unidade.
.NET Community Toolkit