IRONSOFTWAREHOME
ATUALIZAÇÕES DO DESENVOLVEDOR

Span em C# (Como funciona para desenvolvedores)

Curtis Chau
Curtis Chau
Updated: 23 de abril de 2026

Span é um tipo introduzido no C# 7.2 como parte da estrutura Span no namespace System. Ele foi projetado para representar uma região contígua de memória arbitrária. Ao contrário de arrays ou coleções como o heap gerenciado, o Span não possui a memória da pilha ou a região de memória para a qual aponta; Em vez disso, oferece uma visão simplificada dos blocos de memória existentes. Essa característica torna o Span particularmente poderoso para cenários em que você precisa trabalhar com buffers de memória de forma eficiente, sem incorrer em sobrecarga adicional e cenários de código inseguros. Mais adiante neste artigo, veremos também a introdução à biblioteca IronPDF da Iron Software .

Principais características do vão

1. Gerenciamento de memória

Em C#, o Span permite que os desenvolvedores trabalhem diretamente com a memória sem recorrer às alocações tradicionais de heap. Oferece uma maneira de criar fatias de memória a partir de arrays existentes ou outras fontes de memória, eliminando a necessidade de cópias de memória adicionais.

2. Abstrações de Cópia Zero

Uma das características mais marcantes do Span em C# é a sua abstração de cópia zero. Em vez de duplicar dados, o Span oferece uma maneira eficiente de referenciar a memória existente. Isso é particularmente benéfico em cenários onde copiar grandes quantidades de dados seria impraticável ou muito caro.

3. Operações do tipo ponteiro

Embora o C# tenha sido tradicionalmente uma linguagem segura e de alto nível, o Span introduz um grau de manipulação de memória de baixo nível semelhante ao trabalho com ponteiros em linguagens como C ou C++. Os desenvolvedores podem executar operações semelhantes a ponteiros sem sacrificar a segurança e a natureza gerenciada do C#.

4. Natureza Imutável

Apesar de suas capacidades de acesso à memória de baixo nível, o Span em C# permanece imutável. Isso significa que, embora permita a manipulação da memória, garante a segurança ao impedir modificações não intencionais.

Exemplo

using System;

class Program
{
    static void Main()
    {
        int[] array = { 1, 2, 3, 4, 5 };

        // Create a span that points to the entire array
        Span<int> span = array;

        // Modify the data using the span
        span[2] = 10;

        // Print the modified array
        foreach (var item in array)
        {
            Console.WriteLine(item);
        }
    }
}

Somente leitura

Enquanto Span é mutável e permite modificações nos dados subjacentes, ReadOnlySpan é uma visão imutável da memória. Ela fornece uma interface somente leitura para uma região contígua de memória, tornando-a adequada para cenários em que você precisa apenas ler os dados sem modificá-los.

Aqui estão alguns pontos-chave.

1. Modo somente leitura

Como o nome sugere, ReadOnlySpan permite criar uma visão de leitura de um bloco de memória. Isso significa que você não pode modificar os elementos através de um ReadOnlySpan.

2. Representação da memória

Como Span, ReadOnlySpan não possui a memória para a qual aponta. Refere-se à memória existente e pode apontar para arrays, memória alocada na pilha ou memória nativa.

3. Benefícios de desempenho

Como Span, ReadOnlySpan pode oferecer melhor desempenho em comparação com tipos de coleção tradicionais, especialmente ao lidar com grandes volumes de dados, pois reduz a necessidade de cópias.

4. Sem verificação de limites

Assim como Span, ReadOnlySpan não realiza verificação de limites. É responsabilidade do desenvolvedor garantir que as operações permaneçam dentro dos limites da memória subjacente.

5. Utilização com fatiamento de matrizes

ReadOnlySpan suporta slicing, permitindo criar subspans que referenciam uma parte da memória original.

Exemplo

using System;

class Program
{
    static void Main()
    {
        int[] array = { 1, 2, 3, 4, 5 };

        // Create a read-only span that points to the entire array
        ReadOnlySpan<int> readOnlySpan = array;

        // Access and print the data through the read-only span
        foreach (var item in readOnlySpan)
        {
            Console.WriteLine(item);
        }

        // Note: The following line would result in a compilation error since readOnlySpan is read-only.
        // readOnlySpan[2] = 10;
    }
}

Existem muitas maneiras diferentes de criar um ReadOnlySpan e trabalhar com ele. Abaixo seguem alguns exemplos.

1. Criando ReadOnlySpan a partir de uma string

string msg = "Hello, World!";
ReadOnlySpan<char> span1 = msg.AsSpan();
// Read-only manipulation
char firstChar = span1[0];
Console.WriteLine(firstChar); // Outputs: H

2. Trabalhando com substrings

Use Slice on the ReadOnlySpan<char>

// Example usage of Slice method on ReadOnlySpan<char>
ReadOnlySpan<char> spanFromString = "Sample String".AsSpan();
ReadOnlySpan<char> substringSpan = spanFromString.Slice(7, 6); // Extracts 'String'

3. Passando uma substring para um método

Pass ReadOnlySpan<char> como um parâmetro para o método.

void ProcessSubstringfromReadOnlySpan(ReadOnlySpan<char> substring)
{
    // Perform operations on the substring
}

// Usage
ReadOnlySpan<char> spanFromString = "Sample String".AsSpan();
ProcessSubstringfromReadOnlySpan(spanFromString.Slice(7, 6));

4. Pesquisando dentro de uma string

ReadOnlySpan<char> para pesquisar dentro de uma string com IndexOf().

ReadOnlySpan<char> stringSpan = "Hello, World!".AsSpan();
int index = stringSpan.IndexOf('W');
Console.WriteLine(index); // Outputs: 7

5. Utilizando arquivos mapeados em memória

Somente leitura<char> Pode ser mais eficiente com arquivos mapeados em memória.

using System;
using System.IO.MemoryMappedFiles;

class Program
{
    static void ProcessData(ReadOnlySpan<byte> data)
    {
        // Process data directly from the memory-mapped file
    }

    static void Main()
    {
        using (var memmf = MemoryMappedFile.CreateFromFile("data.bin"))
        {
            using (var accessor = memmf.CreateViewAccessor())
            {
                byte[] buffer = new byte[accessor.Capacity];
                accessor.ReadArray(0, buffer, 0, buffer.Length);

                ReadOnlySpan<byte> dataSpan = new ReadOnlySpan<byte>(buffer);
                ProcessData(dataSpan);
            }
        }
    }
}

6. Manipulação eficiente de strings

Somente leitura<char> Pode ser usado para manipulação eficiente de strings.

Span<char> newSpan = new char[6];
ReadOnlySpan<char> spanFromString = "Sample String".AsSpan().Slice(7, 6);
spanFromString.CopyTo(newSpan);
Console.WriteLine(new string(newSpan)); // Outputs: String

7. Passando substrings para APIs

Ao trabalhar com bibliotecas externas ou APIs que operam em intervalos de caracteres.

void ExternalApiMethod(ReadOnlySpan<char> data)
{
    // Call the external API with the character span
}

// Usage
ReadOnlySpan<char> spanFromString = "Sample String".AsSpan();
ExternalApiMethod(spanFromString.Slice(7, 6));

Somente leitura<char> Oferece uma maneira de trabalhar com strings de forma mais eficiente, especialmente em cenários onde a alocação e a cópia de memória devem ser minimizadas. É uma ferramenta poderosa para otimizar código crítico em termos de desempenho e pode ser particularmente benéfica ao lidar com grandes quantidades de dados em formato de string.

Limitações de extensão

Embora o Span em C# seja um recurso poderoso com inúmeras vantagens, ele apresenta certas limitações e considerações, principalmente no contexto de memória contígua e não contígua. Vamos explorar essas limitações:

1. Buffers de memória contígua

1.1 Sem gerenciamento automático de memória

Span não gerencia a memória para a qual aponta. Isso significa que se a memória gerenciada subjacente for liberada ou sair do escopo, o uso de Span resultará em comportamento indefinido ou possíveis falhas. Os desenvolvedores precisam garantir que a memória subjacente ainda seja válida ao usar um Span.

1.2 Sem coleta de lixo

Como Span não possui memória, ele não está sujeito à coleta de lixo. Portanto, é necessário cuidado ao trabalhar com memória alocada na pilha ou memória que tenha um tempo de vida mais curto que o próprio Span.

1.3 A verificação de limites está desativada.

Span e ReadOnlySpan não realizam verificação de limites por padrão. Isso pode levar ao acesso a locais de memória inválidos se não for usado com cuidado. Os desenvolvedores precisam garantir manualmente que as operações em um Span permaneçam dentro dos limites da memória subjacente.

1.4 Sem suporte para memória não contígua

Span é projetado para trabalhar com memória contígua. Se você tiver memória não contígua ou precisar representar estruturas de dados mais complexas, Span pode não ser a escolha mais apropriada.

1.5 Nem todas as operações são suportadas

Embora Span suporte muitas operações comuns como slicing, indexação e iteração, nem todas as operações são suportadas. Por exemplo, você não pode redimensionar um Span, e certas operações que envolvem a alteração do comprimento da memória subjacente não são permitidas.

1.6 Compatibilidade limitada com a plataforma

Embora Span faça parte do .NET Standard e .NET Core, pode não estar disponível em todas as plataformas ou ambientes. É crucial garantir que a sua plataforma de destino suporte Span se planeja usá-lo em seu código.

2. Buffers de memória não contíguos

2.1 Suporte limitado para memória não contígua

ReadOnlySpan é projetado principalmente para funcionar perfeitamente com blocos de memória contígua ou buffers. Pode não ser a opção mais adequada para cenários que envolvam buffers de memória não contíguos ou estruturas com lacunas de memória.

2.2 Limitações Estruturais

Certas estruturas de dados ou cenários que dependem de memória não contígua podem não alinhar bem com ReadOnlySpan. Por exemplo, estruturas de dados como listas encadeadas ou estruturas gráficas podem não ser adequadas devido à exigência de memória contígua do ReadOnlySpan.

2.3 Operações complexas com ponteiros

Em situações que envolvem memória não contígua, particularmente aquelas que requerem aritmética de ponteiro intricada, ReadOnlySpan pode não oferecer o mesmo controle e flexibilidade de baixo nível que os ponteiros brutos em linguagens como C++. Nesses casos, utilizar código inseguro com ponteiros pode ser mais apropriado.

2.4 Falta de suporte direto em algumas APIs

Semelhante à memória contígua, é importante notar que nem todas as APIs ou bibliotecas podem suportar diretamente memória não contígua representada por ReadOnlySpan. A adaptação a esses cenários pode exigir etapas intermediárias adicionais ou conversões para garantir a compatibilidade.

Span e memória não gerenciada

Em C#, o Span pode ser usado de forma eficaz com memória não gerenciada para executar operações relacionadas à memória de maneira controlada e eficiente. Memória não gerenciada refere-se à memória que não é gerenciada pelo coletor de lixo do ambiente de execução .NET e, frequentemente, envolve o uso de alocações e desalocações de memória nativa. Eis como o Span pode ser utilizado com memória não gerenciada em C#.

Alocando memória não gerenciada

Para alocar memória não gerenciada, você pode usar a classe System.Runtime.InteropServices.MemoryMarshal. O método Marshal.AllocHGlobal aloca memória e retorna um ponteiro para o bloco alocado. A memória alocada ou o endereço de memória é armazenado em um ponteiro unmanagedMemory e terá acesso de leitura e gravação. Regiões contíguas da memória podem ser acessadas facilmente.

using System;
using System.Runtime.InteropServices;

class Program
{
    static void Main()
    {
        const int bufferSize = 100;
        IntPtr unmanagedMemory = Marshal.AllocHGlobal(bufferSize);

        // Create a Span from the unmanaged memory
        Span<byte> span = new Span<byte>(unmanagedMemory.ToPointer(), bufferSize);

        // Use the Span as needed...
        
        // Don't forget to free the unmanaged memory when done
        Marshal.FreeHGlobal(unmanagedMemory);
    }
}

No código fonte acima, alocamos um bloco de memória não gerenciada usando Marshal.AllocHGlobal e então criamos um Span<byte> usando o ponteiro obtido da memória não gerenciada. Isso nos permite trabalhar com memória não gerenciada usando a API Span, que já conhecemos. É importante observar que, ao trabalhar com memória não gerenciada, você é responsável por gerenciar a alocação e a desalocação da memória.

Copiando dados de e para memória não gerenciada

Span fornece métodos como Slice, CopyTo, e ToArray que podem ser usados para copiar dados entre memória gerenciada e não gerenciada de forma eficiente.

using System;
using System.Runtime.InteropServices;

class Program
{
    static void Main()
    {
        // Managed array to copy data from
        int[] sourceArray = { 1, 2, 3, 4, 5 };
        
        // Allocate unmanaged memory for the destination data
        IntPtr destinationPointer = Marshal.AllocHGlobal(sourceArray.Length * sizeof(int));
        try
        {
            // Create a Span<int> from the source array
            Span<int> sourceSpan = sourceArray;
            
            // Create a Span<int> from the allocated unmanaged memory
            Span<int> destinationSpan = new Span<int>(destinationPointer.ToPointer(), sourceArray.Length);
            
            // Copy data from the source Span<int> to the destination Span<int>
            sourceSpan.CopyTo(destinationSpan);
            
            // Print the values in the destination memory
            Console.WriteLine("Values in the destination memory:");
            foreach (var value in destinationSpan)
            {
                Console.Write($"{value} ");
            }
        }
        finally
        {
            // Deallocate the unmanaged memory when done
            Marshal.FreeHGlobal(destinationPointer);
        }
    }
}

Neste exemplo:

  • Marshal.AllocHGlobal aloca memória não gerenciada para os dados de destino.
  • new Span<int>(destinationPointer.ToPointer(), sourceArray.Length) cria um Span<int> da memória não gerenciada alocada.
  • O método sourceSpan.CopyTo(destinationSpan) copia os dados da matriz gerenciada para a memória não gerenciada.
  • Os valores na memória de destino são impressos para verificar a operação de cópia.
  • O método Marshal.FreeHGlobal(destinationPointer) é usado para desalocar a memória não gerenciada quando terminado.

Utilizando código inseguro

Ao lidar com memória não gerenciada, você também pode usar código inseguro com ponteiros. Nesses casos, você pode obter um ponteiro do Span usando o método Unsafe.AsPointer().

using System;
using System.Runtime.InteropServices;
using System.Runtime.CompilerServices;

class Program
{
    static void Main()
    {
        const int bufferSize = 100;
        IntPtr unmanagedMemory = Marshal.AllocHGlobal(bufferSize);

        // Create a Span from the unmanaged memory
        Span<byte> span = new Span<byte>(unmanagedMemory.ToPointer(), bufferSize);

        // Use unsafe code to work with pointers
        unsafe
        {
            byte* pointer = (byte*)Unsafe.AsPointer(ref MemoryMarshal.GetReference(span));
            // Use the pointer as needed...
        }

        // Don't forget to free the unmanaged memory when done
        Marshal.FreeHGlobal(unmanagedMemory);
    }
}

Neste exemplo, usamos o método Unsafe.AsPointer para obter um ponteiro do Span. Isso nos permite usar código inseguro ao trabalhar diretamente com ponteiros.

Lembre-se: ao trabalhar com memória não gerenciada, é crucial gerenciar a alocação e a desalocação adequadamente para evitar vazamentos de memória. Sempre libere a memória não gerenciada usando métodos apropriados, como Marshal.FreeHGlobal(). Além disso, tenha cautela ao usar código inseguro, pois ele pode introduzir riscos potenciais de segurança se não for tratado adequadamente.

Span e chamadas de método assíncronas

Utilizar Span em conjunto com chamadas de métodos assíncronas em C# é uma combinação poderosa, especialmente ao lidar com grandes quantidades de dados ou operações de E/S. O objetivo é lidar com operações assíncronas de forma eficiente, sem copiar dados desnecessariamente. Vamos explorar como você pode aproveitar o Span em cenários assíncronos:

1. Operações de E/S assíncronas:

Ao lidar com operações de I/O assíncronas, como ler ou gravar dados em um fluxo, você pode usar Memory ou Span para trabalhar eficientemente com os dados sem criar buffers adicionais.

using System;
using System.IO;
using System.Threading.Tasks;

class Program
{
    static async Task ProcessDataAsync(Stream stream)
    {
        const int bufferSize = 4096;
        byte[] buffer = new byte[bufferSize];
        while (true)
        {
            int bytesRead = await stream.ReadAsync(buffer.AsMemory());
            if (bytesRead == 0)
                break;

            // Process the data using Span without unnecessary copying
            ProcessData(buffer.AsSpan(0, bytesRead));
        }
    }

    static void ProcessData(Span<byte> data)
    {
        // Perform operations on the data
    }
}

Neste exemplo, o método ReadAsync lê dados de um fluxo para o buffer de forma assíncrona. O método ProcessData processa os dados diretamente do Span<byte> sem copiá-lo para outro buffer.

2. Operações de Arquivo Assíncronas:

Assim como nas operações de E/S, ao lidar com operações assíncronas de arquivos, você pode usar o Span para processar dados de forma eficiente sem cópias adicionais.

using System;
using System.IO;
using System.Threading.Tasks;

class Program
{
    static async Task ProcessFileAsync(string filePath)
    {
        const int bufferSize = 4096;
        using (FileStream fileStream = new FileStream(filePath, FileMode.Open, FileAccess.Read))
        {
            byte[] buffer = new byte[bufferSize];
            while (true)
            {
                int bytesRead = await fileStream.ReadAsync(buffer.AsMemory());
                if (bytesRead == 0)
                    break;

                // Process the data using Span without unnecessary copying
                ProcessData(buffer.AsSpan(0, bytesRead));
            }
        }
    }

    static void ProcessData(Span<byte> data)
    {
        // Perform operations on the data
    }
}

Aqui, o método ReadAsync lê dados de um fluxo de arquivo para o buffer, e o método ProcessData processa os dados diretamente do Span<byte> .

3. Processamento de tarefas assíncronas:

Ao trabalhar com tarefas assíncronas que produzem ou consomem dados, você pode usar Memory ou Span para evitar cópias desnecessárias.

using System;
using System.Linq;
using System.Threading.Tasks;

class Program
{
    static async Task<int> ProcessDataAsync(int[] data)
    {
        // Asynchronous processing of data
        await Task.Delay(1000);
        // Returning the length of the processed data
        return data.Length;
    }

    static async Task Main()
    {
        int[] inputData = Enumerable.Range(1, 1000).ToArray();
        
        // Process the data asynchronously without copying
        int processedLength = await ProcessDataAsync(inputData.AsMemory());
        Console.WriteLine($"Processed data length: {processedLength}");
    }
}

Neste exemplo, o método ProcessDataAsync processa os dados de forma assíncrona e retorna o comprimento dos dados processados ​​sem exigir cópias adicionais.

Apresentando o IronPDF

A biblioteca IronPDF é a mais recente biblioteca C# para PDF da Iron Software , que pode ser usada para gerar documentos PDF visualmente atraentes de forma dinâmica e instantânea usando código C#. O IronPDF oferece uma variedade de recursos, como geração de PDF a partir de HTML, conversão de conteúdo HTML para PDF, mesclagem ou divisão de arquivos PDF, etc.

A principal funcionalidade do IronPDF é a conversão de HTML para PDF , que preserva layouts e estilos. Ele pode gerar PDFs a partir de conteúdo da web, sendo ótimo para relatórios, faturas e documentação. Esta ferramenta permite converter arquivos HTML, URLs e strings HTML em arquivos PDF.

using IronPdf;

class Program
{
    static void Main(string[] args)
    {
        var renderer = new ChromePdfRenderer();

        // 1. Convert HTML String to PDF
        var htmlContent = "<h1>Hello, IronPDF!</h1><p>This is a PDF from an HTML string.</p>";
        var pdfFromHtmlString = renderer.RenderHtmlAsPdf(htmlContent);
        pdfFromHtmlString.SaveAs("HTMLStringToPDF.pdf");

        // 2. Convert HTML File to PDF
        var htmlFilePath = "path_to_your_html_file.html"; // Specify the path to your HTML file
        var pdfFromHtmlFile = renderer.RenderHtmlFileAsPdf(htmlFilePath);
        pdfFromHtmlFile.SaveAs("HTMLFileToPDF.pdf");

        // 3. Convert URL to PDF
        var url = "http://ironpdf.com"; // Specify the URL
        var pdfFromUrl = renderer.RenderUrlAsPdf(url);
        pdfFromUrl.SaveAs("URLToPDF.pdf");
    }
}

Instalação

O IronPDF pode ser instalado usando o gerenciador de pacotes NuGet para o console do IronPDF ou usando o gerenciador de pacotes do Visual Studio.

dotnet add package IronPdf

C# Span (How It Works For Developers): Figure 1 - Install IronPDF using NuGet Package Manager by searching "IronPDF" in the search bar of NuGet Package Manager

using System;
using IronPdf;

class Program
{
    static void Main()
    {
        Console.WriteLine("Generating PDF using IronPDF.");
        var displayFirstName = "<p>First Name is Joe</p>".AsSpan();
        var displayLastName = "<p>Last Name is Doe</p>".AsSpan();
        var displayAddress = "<p>12th Main, 7Th Cross, New York</p>".AsSpan();
        var start = "<html><body>".AsSpan();
        var end = "</body></html>".AsSpan();
        var content = string.Concat(start.ToString(), displayFirstName.ToString(), displayLastName.ToString(), displayAddress.ToString(), end.ToString());
        var pdfDocument = new ChromePdfRenderer();
        pdfDocument.RenderHtmlAsPdf(content).SaveAs("span.pdf");
    }
}

Neste exemplo, estamos usando o Span juntamente com o IronPDF para gerar um documento PDF.

Saída:

C# Span (Como Funciona Para Desenvolvedores): Figura 2 - Saída do Console

PDF Gerado:

C# Span (Como Funciona Para Desenvolvedores): Figura 3 - Saída do PDF

Licenciamento (Teste Gratuito Disponível)

Informações sobre a licença do IronPDF . Essa chave precisa ser inserida no arquivo appsettings.json.

"IronPdf.LicenseKey": "your license key"
JSON

Forneça seu e-mail para obter uma licença de avaliação.

Conclusão

Span em C# fornece uma maneira poderosa e eficiente de trabalhar com memória, oferecendo benefícios em termos de desempenho e flexibilidade. Sua natureza contígua e sem dependência de memória a torna particularmente adequada para cenários onde minimizar alocações e cópias de memória é crucial. Ao utilizar o Span, os desenvolvedores podem obter melhor desempenho em uma variedade de aplicações, desde manipulação de strings até processamento numérico de alto desempenho. Ao entender seus recursos e considerar suas limitações, os desenvolvedores podem aproveitar Span para várias tarefas de manipulação de memória de forma segura e eficiente. Juntamente com a visão geral da biblioteca IronPDF , ela pode ser usada para gerar documentos PDF incríveis sem as limitações de await e yield.

Por favor, visite a página de documentação de início rápido do IronPDF .

Curtis Chau
Redator Técnico

Curtis Chau é bacharel em Ciência da Computação (Universidade Carleton) e se especializa em desenvolvimento front-end, com experiência em Node.js, TypeScript, JavaScript e React. Apaixonado por criar interfaces de usuário intuitivas e esteticamente agradáveis, Curtis gosta de trabalhar com frameworks modernos e criar manuais bem estruturados e visualmente atraentes.

...
Leia mais

Artigos relacionados

Key in blue circle

Obtenha sua chave de avaliação gratuita de 30 dias instantaneamente.

Your trial license will be sent to your email address

Sem limitações. 100% desbloqueado. Sem cartão de crédito.

bullet_checkedNão é necessário cartão de crédito nem criação de conta.Sem limitações. 100% desbloqueado. Sem cartão de crédito.
  • Logo Aetna
  • Logo NASA
  • Logo GE
  • Logo Porsche
  • Logo USDA
  • Logo Qatar
Join Millions of Engineers who’ve tried IronPDF
Agende sua demonstração ao vivo gratuita.
Booking Badge

Aprovado por milhões de engenheiros em todo o mundo.

Logotipos dos clientes da Iron Software
Agende sua consulta sem compromisso.
Preencha o formulário abaixo ou envie um e-mail para sales@ironsoftware.com
Os seus dados serão sempre mantidos em sigilo.
Aprovado por milhões de engenheiros em todo o mundo.
Logotipos dos clientes da Iron Software
Obtenha sua chave de avaliação gratuita de 30 dias instantaneamente.
Não é necessário cartão de crédito nem criação de conta.