.NET-HILFE

C# Span (Wie es für Entwickler funktioniert)

Chipego
Chipego Kalinda
6. März 2024
Teilen Sie:

*Span ist ein Typ, der in C# 7.2 als Teil der Spanstruktur im Namespace System. Er ist so konzipiert, dass er einen zusammenhängenden Bereich eines beliebigen Speichers darstellt. Im Gegensatz zu Arrays oder Sammlungen, wie z. B. Managed Heap, ist Span nicht Eigentümer des Stapelspeichers oder des Speicherbereichs, auf den er zeigt; stattdessen bietet es eine leichtgewichtige Sicht auf vorhandene Speicherblöcke. Diese Eigenschaft macht Span besonders leistungsfähig für Szenarien, in denen Sie effizient mit Speicherpuffern arbeiten müssen, ohne zusätzlichen Overhead und unsichere Codeszenarien zu verursachen. Später in diesem Artikel werden wir auch die Einführung in dieIronPDF-Bibliothek vonIron Software.

Hauptmerkmale der Spanne

1. Speicherverwaltung

Span in C# ermöglicht es Entwicklern, direkt mit Speicher zu arbeiten, ohne auf traditionelle Heap-Zuweisungen zurückgreifen zu müssen. Es bietet eine Möglichkeit, Speicherabschnitte aus bestehenden Arrays oder anderen Speicherquellen zu erstellen, wodurch zusätzliche Speicherkopien überflüssig werden.

2. Null-Kopie-Abstraktionen

Eines der herausragenden Merkmale von C# Span sind seine Null-Kopie-Abstraktionen. Anstatt Daten zu duplizieren, bietet Span eine Möglichkeit, effizient auf vorhandenen Speicher zu verweisen. Dies ist besonders vorteilhaft für Szenarien, in denen das Kopieren großer Datenmengen unpraktisch oder zu kostspielig wäre.

3. Zeiger-ähnliche Operationen

Während C# traditionell eine sichere High-Level-Sprache ist, führt Span ein gewisses Maß an Low-Level-Speichermanipulation ein, das der Arbeit mit Zeigern in Sprachen wie C oder C++ ähnelt. Entwickler können zeigerähnliche Operationen durchführen, ohne auf die Sicherheit und den verwalteten Charakter von C# zu verzichten.

4. Unveränderliche Natur

Trotz seiner Möglichkeiten für den Speicherzugriff auf niedriger Ebene bleibt C# Span unveränderlich. Das bedeutet, dass es zwar die Manipulation des Speichers erlaubt, aber gleichzeitig die Sicherheit erhöht, indem es unbeabsichtigte Änderungen verhindert.

Beispiel

using System;
class Program
{
    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);
        }
    }
}
using System;
class Program
{
    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);
        }
    }
}

ReadOnlySpan

Während Spanveränderlich ist und Änderungen an den zugrunde liegenden Daten zulässt, ist ReadOnlySpanist eine unveränderliche Ansicht des Speichers. Sie bietet eine Nur-Lese-Schnittstelle zu einem zusammenhängenden Speicherbereich und eignet sich daher für Szenarien, in denen Sie die Daten nur lesen, aber nicht verändern müssen.

Hier sind einige wichtige Punkte.

1. Schreibgeschützte Ansicht

Wie der Name schon sagt, ist ReadOnlySpanermöglicht es Ihnen, eine schreibgeschützte Ansicht eines Speicherblocks zu erstellen. Das bedeutet, dass Sie die Elemente nicht über eine ReadOnlySpan.

2. Darstellung des Speichers

Wie Span, ReadOnlySpanist nicht Eigentümer des Speichers, auf den es zeigt. Er bezieht sich auf vorhandenen Speicher und kann auf Arrays, Stack-allocated Memory oder Native Memory verweisen.

3. Leistungsvorteile

Wie Span, ReadOnlySpankann im Vergleich zu herkömmlichen Erfassungsarten eine bessere Leistung bieten, insbesondere bei großen Datenmengen, da weniger Kopiervorgänge erforderlich sind.

4. Prüfung ohne Grenzen

Wie bei Span, ReadOnlySpanführt keine Überprüfung der Grenzen durch. Es liegt in der Verantwortung des Entwicklers, sicherzustellen, dass die Operationen innerhalb der Grenzen des zugrunde liegenden Speichers bleiben.

5. Verwendung mit Array Slicing

ReadOnlySpanunterstützt das Slicing, d. h. Sie können Teilbereiche erstellen, die auf einen Teil des ursprünglichen Speichers verweisen.

Beispiel

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;
    }
}
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;
    }
}

Es gibt viele verschiedene Möglichkeiten, ReadOnlySpan zu erstellen und mit ihm zu arbeiten. Nachstehend einige Beispiele.

1. Erstellen von ReadOnlySpan aus String

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

2. Arbeiten mit Teilstrings

Slice auf der ReadOnlySpan verwenden

ReadOnlySpan<char> substringSpan = spanFromString.Slice(startIndex, length);
ReadOnlySpan<char> substringSpan = spanFromString.Slice(startIndex, length);

3. Übergabe von Substraten an eine Methode

Pass ReadOnlySpanals Parameter für die Methode.

void ProcessSubstringfromReadOnlySpan(ReadOnlySpan<char> substring)
{
    // Perform operations on the substring
}
// Usage
ProcessSubstringfromReadOnlySpan(spanFromString.Slice(startIndex, length));
void ProcessSubstringfromReadOnlySpan(ReadOnlySpan<char> substring)
{
    // Perform operations on the substring
}
// Usage
ProcessSubstringfromReadOnlySpan(spanFromString.Slice(startIndex, length));

4. Suche innerhalb einer Zeichenkette

ReadOnlySpanfür die Suche innerhalb einer Zeichenkette mit IndexOf().

int index = stringSpan.IndexOf('W');
int index = stringSpan.IndexOf('W');

5. Verwendung von Memory-Mapped-Dateien

ReadOnlySpankann mit Memory-Mapped-Dateien effizienter sein.

using (var memmf = MemoryMappedFile.CreateFromFile("data.bin"))
{
    using (var accessor = memmf.CreateViewAccessor())
    {
        ReadOnlySpan<byte> dataSpan;
        accessor.Read(0, out dataSpan);
        // Process data directly from the memory-mapped file
        ProcessData(dataSpan);
    }
}
using (var memmf = MemoryMappedFile.CreateFromFile("data.bin"))
{
    using (var accessor = memmf.CreateViewAccessor())
    {
        ReadOnlySpan<byte> dataSpan;
        accessor.Read(0, out dataSpan);
        // Process data directly from the memory-mapped file
        ProcessData(dataSpan);
    }
}

6. Effiziente Manipulation von Zeichenketten

ReadOnlySpankann für die effiziente Manipulation von Zeichenketten verwendet werden.

// Replace a character in a substring without creating a new string
spanFromString.Slice(startIndex, length).CopyTo(newSpan);
// Replace a character in a substring without creating a new string
spanFromString.Slice(startIndex, length).CopyTo(newSpan);

7. Übergabe von Substraten an APIs

Bei der Arbeit mit externen Bibliotheken oder APIs, die mit Zeichenabständen arbeiten.

void ExternalApiMethod(ReadOnlySpan<char> data)
{
    // Call the external API with the character span
}
// Usage
ExternalApiMethod(spanFromString.Slice(startIndex, length));
void ExternalApiMethod(ReadOnlySpan<char> data)
{
    // Call the external API with the character span
}
// Usage
ExternalApiMethod(spanFromString.Slice(startIndex, length));

ReadOnlySpanbietet eine Möglichkeit, effizienter mit Zeichenketten zu arbeiten, insbesondere in Szenarien, in denen Speicherzuweisungen und Kopieren minimiert werden sollen. Es ist ein leistungsfähiges Werkzeug zur Optimierung von leistungskritischem Code und kann besonders bei großen Mengen an Zeichenkettendaten von Vorteil sein.

Spannenbegrenzungen

Obwohl Span in C# eine leistungsstarke Funktion mit zahlreichen Vorteilen ist, gibt es auch einige Einschränkungen und Überlegungen, insbesondere im Zusammenhang mit zusammenhängendem und nicht zusammenhängendem Speicher. Lassen Sie uns diese Einschränkungen untersuchen:

1. Zusammenhängende Speicherpuffer

1.1 Keine automatische Speicherverwaltung

Spannweiteverwaltet den Speicher, auf den es zeigt, nicht. Das bedeutet, dass, wenn der zugrunde liegende verwaltete Speicher freigegeben wird oder aus dem Anwendungsbereich verschwindet, die Verwendung des Spanführt zu undefiniertem Verhalten oder möglichen Abstürzen. Die Entwickler müssen sicherstellen, dass der zugrundeliegende Speicher noch gültig ist, wenn sie eine Span.

1.2 Keine Müllabfuhr

Da Spankeinen Speicher besitzt, unterliegt er nicht der Garbage Collection. Daher müssen Sie vorsichtig sein, wenn Sie mit Stack-zugeordnetem Speicher oder Speicher arbeiten, der eine kürzere Lebensdauer hat als der Spanselbst.

1.3 Bounds Checking ist deaktiviert

Spannweiteund ReadOnlySpannweiteführen standardmäßig keine Überprüfung der Grenzen durch. Dies kann dazu führen, dass auf ungültige Speicherplätze zugegriffen wird, wenn nicht sorgfältig damit umgegangen wird. Die Entwickler müssen manuell sicherstellen, dass die Operationen auf einem Spaninnerhalb der Grenzen des zugrunde liegenden Speichers bleiben.

1.4 Keine Unterstützung für nicht zusammenhängenden Speicher

Spannweiteist für die Arbeit mit zusammenhängendem Speicher ausgelegt. Wenn Sie nicht zusammenhängenden Speicher haben oder komplexere Datenstrukturen darstellen müssen, können Sie Spanist möglicherweise nicht die beste Wahl.

1.5 Es werden nicht alle Operationen unterstützt

Während Spanunterstützt viele gängige Operationen wie Slicing, Indexierung und Iteration, aber nicht alle Operationen werden unterstützt. Sie können zum Beispiel die Größe einer Spanne nicht ändernund bestimmte Operationen, bei denen die Länge des zugrunde liegenden Speichers verändert wird, sind nicht zulässig.

1.6 Eingeschränkte Plattformkompatibilität

Während Spanteil des .NET Standards und .NET Core ist, ist es möglicherweise nicht auf allen Plattformen oder Umgebungen verfügbar. Es ist von entscheidender Bedeutung, dass Ihre Zielplattform die Spanwenn Sie es in Ihrem Code verwenden wollen.

2. Nicht zusammenhängende Speicherpuffer

2.1 Eingeschränkte Unterstützung für nicht zusammenhängenden Speicher

ReadOnlySpanist in erster Linie darauf ausgelegt, nahtlos mit zusammenhängenden Speicherblöcken oder Puffern zu arbeiten. Es ist möglicherweise nicht die beste Wahl für Szenarien, in denen nicht zusammenhängende Speicherpuffer oder Strukturen mit Lücken im Speicher betroffen sind.

2.2 Strukturelle Beschränkungen

Bestimmte Datenstrukturen oder Szenarien, die auf nicht zusammenhängenden Speicher angewiesen sind, passen möglicherweise nicht gut zu ReadOnlySpan. So sind beispielsweise Datenstrukturen wie verknüpfte Listen oder Graphenstrukturen aufgrund der Anforderungen von ReadOnlySpan an den zusammenhängenden Speicher möglicherweise nicht gut geeignet.

2.3 Komplexe Zeigeroperationen

In Situationen, in denen es um nicht zusammenhängenden Speicher geht, insbesondere wenn komplizierte Zeigerarithmetik erforderlich ist, kann ReadOnlySpanbieten möglicherweise nicht die gleiche Kontrolle auf niedriger Ebene und Flexibilität wie rohe Zeiger in Sprachen wie C++. In solchen Fällen könnte die Verwendung von unsicherem Code mit Zeigern sinnvoller sein.

2.4 Fehlende direkte Unterstützung in einigen APIs

Ähnlich wie bei zusammenhängendem Speicher ist es wichtig zu beachten, dass nicht alle APIs oder Bibliotheken nicht zusammenhängenden Speicher direkt unterstützen, der durch ReadOnlySpan. Die Anpassung an solche Szenarien kann zusätzliche Zwischenschritte oder Konvertierungen erforderlich machen, um die Kompatibilität zu gewährleisten.

Span und nicht verwalteter Speicher

In C# kann Span effektiv mit nicht verwaltetem Speicher verwendet werden, um speicherbezogene Operationen auf kontrollierte und effiziente Weise durchzuführen. Unverwalteter Speicher bezieht sich auf Speicher, der nicht vom Garbage Collector der .NET-Laufzeitumgebung verwaltet wird, und beinhaltet oft die Verwendung von nativen Speicherzuweisungen und -freigaben. Hier ist, wie Span kann mit unmanaged Speicher in C# verwendet werden.

Zuweisung von nicht verwaltetem Speicher

Um nicht verwalteten Speicher zuzuweisen, können Sie die Klasse System.Runtime.InteropServices.MemoryMarshal verwenden. Die Methode Marshal.AllocHGlobal weist Speicher zu und gibt einen Zeiger auf den zugewiesenen Block zurück. Der zugewiesene Speicher oder die Speicheradresse wird in einem unmanagedMemory-Zeiger gehalten und hat Lese- und Schreibzugriff. Auf die zusammenhängenden Bereiche des Speichers kann leicht zugegriffen werden.

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);
    }
}
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);
    }
}

Im obigen Quellcode weisen wir mit Marshal.AllocHGlobal einen Block nicht verwalteten Speichers zu und erstellen dann eine Spanunter Verwendung des Zeigers, der aus dem nicht verwalteten Speicher stammt. Dadurch können wir mit nicht verwaltetem Speicher arbeiten, indem wir die bekannte Span-API verwenden. Es ist wichtig zu wissen, dass Sie bei der Arbeit mit nicht verwaltetem Speicher für die Verwaltung der Zuweisung und Freigabe des Speichers verantwortlich sind.

Kopieren von Daten in und aus nicht verwaltetem Speicher

Span bietet Methoden wie Slice, CopyTo und ToArray, die für das effiziente Kopieren von Daten zwischen verwaltetem und nicht verwaltetem Speicher verwendet werden können.

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 = MemoryMarshal.Allocate<int>(sourceArray.Length);
        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 = MemoryMarshal.Cast<int, byte>(destinationPointer, 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
            MemoryMarshal.Free(destinationPointer);
        }
    }
}
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 = MemoryMarshal.Allocate<int>(sourceArray.Length);
        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 = MemoryMarshal.Cast<int, byte>(destinationPointer, 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
            MemoryMarshal.Free(destinationPointer);
        }
    }
}

In diesem Beispiel:

MemoryMarshal.Allocate(sourceArray.Length) weist nicht verwalteten Speicher für die Zieldaten zu. MemoryMarshal.Cast<int, byte>(destinationPointer, sourceArray.Length) erstellt eine Spanneaus dem zugewiesenen unverwalteten Speicher. Die Funktion sourceSpan.CopyTo(destinationSpan) methode kopiert die Daten aus dem verwalteten Array in den nicht verwalteten Speicher. Die Werte im Zielspeicher werden ausgedruckt, um den Kopiervorgang zu überprüfen. Das GedächtnisMarschall.Free(zielZeiger) methode wird verwendet, um den nicht verwalteten Speicher wieder freizugeben, wenn er fertig ist.

Unsicheren Code verwenden

Wenn Sie mit nicht verwaltetem Speicher arbeiten, können Sie auch unsicheren Code mit Zeigern verwenden. In solchen Fällen können Sie einen Zeiger aus dem Span erhalten, indem Sie die Funktion Unsafe.AsPointer() methode.

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 unsafe code to work with pointers
        // ref t
        unsafe
        {
            byte* pointer = (byte*)Unsafe.AsPointer(ref struct MemoryMarshal.GetReference(span));
            // Use the pointer as needed...
        }
        // Don't forget to free the unmanaged memory when done
        Marshal.FreeHGlobal(unmanagedMemory);
    }
}
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 unsafe code to work with pointers
        // ref t
        unsafe
        {
            byte* pointer = (byte*)Unsafe.AsPointer(ref struct MemoryMarshal.GetReference(span));
            // Use the pointer as needed...
        }
        // Don't forget to free the unmanaged memory when done
        Marshal.FreeHGlobal(unmanagedMemory);
    }
}

In diesem Beispiel verwenden wir die Methode Unsafe.AsPointer, um einen Zeiger von Span zu erhalten. Dies ermöglicht uns die Verwendung von unsicherem Code, wenn wir direkt mit Zeigern arbeiten.

Denken Sie daran, dass es bei der Arbeit mit nicht verwaltetem Speicher wichtig ist, die Zuweisung und Freigabe richtig zu verwalten, um Speicherlecks zu vermeiden. Geben Sie nicht verwalteten Speicher immer mit geeigneten Methoden frei, z. B. mit Marshal.FreeHGlobal(). Seien Sie außerdem vorsichtig bei der Verwendung von unsicherem Code, da dieser bei unsachgemäßer Handhabung potenzielle Sicherheitsrisiken bergen kann.

Span und asynchrone Methodenaufrufe

Die Verwendung von Span in Verbindung mit asynchronen Methodenaufrufen in C# ist eine leistungsstarke Kombination, vor allem wenn es um große Datenmengen oder E/A-Operationen geht. Ziel ist es, asynchrone Operationen ohne unnötiges Kopieren von Daten effizient abzuwickeln. Lassen Sie uns untersuchen, wie Sie Span in asynchronen Szenarien nutzen können:

1. Asynchrone E/A-Operationen:

Bei asynchronen E/A-Operationen, wie dem Lesen oder Schreiben von Daten in einen Stream, können Sie Memoryoder Spannweiteum effizient mit den Daten zu arbeiten, ohne zusätzliche Puffer zu erzeugen.

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));
    }
}
void ProcessData(Span<byte> data)
{
    // Perform operations on the data
}
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));
    }
}
void ProcessData(Span<byte> data)
{
    // Perform operations on the data
}

In diesem Beispiel liest die Methode ReadAsync asynchron Daten aus einem Stream in den Puffer. Die ProcessData-Methode verarbeitet dann die Daten direkt aus dem Spanohne sie in einen anderen Puffer zu kopieren.

2. Asynchrone Dateioperationen:

Ähnlich wie bei E/A-Operationen können Sie bei asynchronen Dateioperationen Span verwenden, um Daten ohne zusätzliches Kopieren effizient zu verarbeiten.

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));
        }
    }
}
void ProcessData(Span<byte> data)
{
    // Perform operations on the data
}
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));
        }
    }
}
void ProcessData(Span<byte> data)
{
    // Perform operations on the data
}

Hier liest die ReadAsync-Methode Daten aus einem Dateistrom in den Puffer, und die ProcessData-Methode verarbeitet die Daten direkt aus dem Span.

3. Asynchrone Aufgabenverarbeitung:

Wenn Sie mit asynchronen Aufgaben arbeiten, die Daten produzieren oder verbrauchen, können Sie Memoryoder Spannweiteum unnötiges Kopieren zu vermeiden.

async Task<int> ProcessDataAsync(int[] data)
{
    // Asynchronous processing of data
    await Task.Delay(1000);
    // Returning the length of the processed data
    return data.Length;
}
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}");
}
async Task<int> ProcessDataAsync(int[] data)
{
    // Asynchronous processing of data
    await Task.Delay(1000);
    // Returning the length of the processed data
    return data.Length;
}
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}");
}

In diesem Beispiel verarbeitet die Methode ProcessDataAsync die Daten asynchron und gibt die Länge der verarbeiteten Daten zurück, ohne dass zusätzliche Kopien erforderlich sind.

Einführung in IronPDF

Überblick über die IronPDF-Bibliothek ist die neueste C# PDF-Bibliothek vonIron Software mit dem sich schöne PDF-Dokumente dynamisch mit C#-Code erzeugen lassen. IronPDF bietet eine Vielzahl von Funktionen, wie z. B. PDF-Erzeugung aus HTML, Konvertierung von HTML-Inhalten in PDF, Zusammenführen oder Teilen von PDF-Dateien usw.

Das Hauptmerkmal von IronPDF ist seineHTML-zu-PDF-Funktionalitätdie Layouts und Stile beibehält. Es kann PDFs aus Webinhalten generieren und eignet sich daher hervorragend für Berichte, Rechnungen und Dokumentationen. Dieses Tool unterstützt die Umwandlung von HTML-Dateien, URLs und HTML-Strings in PDF-Dateien.

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");
    }
}
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");
    }
}

Einrichtung

IronPDF kann mit dem BefehlNuGet-Paketmanager für IronPDF konsole oder mit dem Visual Studio-Paketmanager.

dotnet add package IronPdf
// Or
Install-Package IronPdf
dotnet add package IronPdf
// Or
Install-Package IronPdf

C#-Spanne(Wie es für Entwickler funktioniert): Abbildung 1 - Installieren Sie IronPDF mit dem NuGet Package Manager, indem Sie in der Suchleiste des NuGet Package Manager nach ironpdf suchen

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

In diesem Beispiel verwenden wir Span zusammen mit IronPDF, um ein PDF-Dokument zu erzeugen.

Ausgang:

C#-Spanne(Wie es für Entwickler funktioniert): Abbildung 2 - Konsolenausgabe

Generierte PDF:

C#-Spanne(Wie es für Entwickler funktioniert): Abbildung 3 - PDF-Ausgabe

Lizenzierung (kostenlose Testversion verfügbar)

IronPDF-Lizenzinformationen. Dieser Schlüssel muss in appsettings.json platziert werden.

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

Geben Sie Ihre E-Mail-Adresse an, um eine Testlizenz zu erhalten.

Schlussfolgerung

Spannweitein C# bietet eine leistungsstarke und effiziente Möglichkeit, mit dem Speicher zu arbeiten, und bietet Vorteile in Bezug auf Leistung und Flexibilität. Die nicht-besitzende, zusammenhängende Natur macht es besonders geeignet für Szenarien, in denen die Minimierung von Speicherzuweisungen und -kopien entscheidend ist. Durch den Einsatz von Span können Entwickler eine bessere Leistung in einer Vielzahl von Anwendungen erzielen, die von der Zeichenkettenmanipulation bis zur leistungsstarken numerischen Verarbeitung reichen. Wenn Entwickler die Funktionen verstehen und ihre Grenzen berücksichtigen, können sie die Spanfür verschiedene Speichermanipulationsaufgaben sicher und effizient. Zusammen mitÜberblick über die IronPDF-Bibliothekkann es verwendet werden, um großartige PDF-Dokumente zu erzeugen, ohne Grenzen zu erwarten und zu erreichen.

Bitte besuchen SieIronPDF's Quick-Start Dokumentationsseite seite.

Chipego
Software-Ingenieur
Chipego hat eine natürliche Fähigkeit zum Zuhören, die ihm hilft, Kundenprobleme zu verstehen und intelligente Lösungen anzubieten. Er trat dem Iron Software-Team 2023 bei, nachdem er einen Bachelor of Science in Informationstechnologie erworben hatte. IronPDF und IronOCR sind die beiden Produkte, auf die sich Chipego konzentriert hat, aber sein Wissen über alle Produkte wächst täglich, da er neue Wege findet, Kunden zu unterstützen. Er genießt die Zusammenarbeit bei Iron Software, da Teammitglieder aus dem gesamten Unternehmen ihre unterschiedlichen Erfahrungen einbringen und so zu effektiven, innovativen Lösungen beitragen. Wenn Chipego nicht an seinem Schreibtisch sitzt, kann man ihn oft bei einem guten Buch oder beim Fußballspielen antreffen.
< PREVIOUS
C# IDE (Wie es für Entwickler funktioniert)
NÄCHSTES >
Opentelemetry C# (Wie es für Entwickler funktioniert)