.NET-HILFE

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

Veröffentlicht 6. März 2024
Teilen Sie:

*Span ist ein Typ, der in C# 7.2 als Teil der Span struktur 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 IronPDF bibliothek von Iron 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);
        }
    }
}
Imports System
Friend Class Program
	Private Sub Main()
		Dim array() As Integer = { 1, 2, 3, 4, 5 }
		' Create a span that points to the entire array
		Dim span As Span(Of Integer) = array
		' Modify the data using the span
		span (2) = 10
		' Print the modified array
		For Each item In array
			Console.WriteLine(item)
		Next item
	End Sub
End Class
VB   C#

ReadOnlySpan

Während Span veränderlich ist und Änderungen an den zugrunde liegenden Daten zulässt, ist ReadOnlySpan ist 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 ReadOnlySpan ermö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, ReadOnlySpan ist 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, ReadOnlySpan kann 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, ReadOnlySpan fü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

ReadOnlySpan unterstü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;
    }
}
Imports System
Friend Class Program
	Shared Sub Main()
		Dim array() As Integer = { 1, 2, 3, 4, 5 }
		' Create a read-only span that points to the entire array
		Dim readOnlySpan As ReadOnlySpan(Of Integer) = array
		' Access and print the data through the read-only span
		For Each item In readOnlySpan
			Console.WriteLine(item)
		Next item
		' Note: The following line would result in a compilation error since readOnlySpan is read-only.
		' readOnlySpan [2] = 10;
	End Sub
End Class
VB   C#

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
Dim msg As String = "Hello, World!"
Dim span1 As ReadOnlySpan(Of Char) = msg.AsSpan()
' Read-only manipulation
Dim firstChar As Char = span1 (0)
Console.WriteLine(firstChar) ' Outputs: H
VB   C#

2. Arbeiten mit Teilstrings

Slice auf der ReadOnlySpan verwenden

ReadOnlySpan<char> substringSpan = spanFromString.Slice(startIndex, length);
ReadOnlySpan<char> substringSpan = spanFromString.Slice(startIndex, length);
Dim substringSpan As ReadOnlySpan(Of Char) = spanFromString.Slice(startIndex, length)
VB   C#

3. Übergabe von Substraten an eine Methode

Pass ReadOnlySpan als 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));
Private Sub ProcessSubstringfromReadOnlySpan(ByVal substring As ReadOnlySpan(Of Char))
	' Perform operations on the substring
End Sub
' Usage
ProcessSubstringfromReadOnlySpan(spanFromString.Slice(startIndex, length))
VB   C#

4. Suche innerhalb einer Zeichenkette

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

int index = stringSpan.IndexOf('W');
int index = stringSpan.IndexOf('W');
Dim index As Integer = stringSpan.IndexOf("W"c)
VB   C#

5. Verwendung von Memory-Mapped-Dateien

ReadOnlySpan kann 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);
    }
}
Using memmf = MemoryMappedFile.CreateFromFile("data.bin")
	Using accessor = memmf.CreateViewAccessor()
		Dim dataSpan As ReadOnlySpan(Of Byte) = Nothing
		accessor.Read(0, dataSpan)
		' Process data directly from the memory-mapped file
		ProcessData(dataSpan)
	End Using
End Using
VB   C#

6. Effiziente Manipulation von Zeichenketten

ReadOnlySpan kann 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);
' Replace a character in a substring without creating a new string
spanFromString.Slice(startIndex, length).CopyTo(newSpan)
VB   C#

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));
Private Sub ExternalApiMethod(ByVal data As ReadOnlySpan(Of Char))
	' Call the external API with the character span
End Sub
' Usage
ExternalApiMethod(spanFromString.Slice(startIndex, length))
VB   C#

ReadOnlySpan bietet 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

Spannweite verwaltet 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 Span fü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 Span keinen 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 Span selbst.

1.3 Bounds Checking ist deaktiviert

Spannweite und ReadOnlySpannweite fü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 Span innerhalb der Grenzen des zugrunde liegenden Speichers bleiben.

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

Spannweite ist 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 Span ist möglicherweise nicht die beste Wahl.

1.5 Es werden nicht alle Operationen unterstützt

Während Span unterstü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 Span teil des .NET-Standards und von .NET Core ist, ist er möglicherweise nicht auf allen Plattformen oder in allen Umgebungen verfügbar. Es ist von entscheidender Bedeutung, dass Ihre Zielplattform die Span wenn Sie es in Ihrem Code verwenden wollen.

2. Nicht zusammenhängende Speicherpuffer

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

ReadOnlySpan ist 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 ReadOnlySpan bieten 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);
    }
}
Imports System
Imports System.Runtime.InteropServices
Friend Class Program
	Shared Sub Main()
		Const bufferSize As Integer = 100
		Dim unmanagedMemory As IntPtr = Marshal.AllocHGlobal(bufferSize)
		' Create a Span from the unmanaged memory
		Dim span As New Span(Of Byte)(unmanagedMemory.ToPointer(), bufferSize)
		' Use the Span as needed...
		' Don't forget to free the unmanaged memory when done
		Marshal.FreeHGlobal(unmanagedMemory)
	End Sub
End Class
VB   C#

Im obigen Quellcode weisen wir mit Marshal.AllocHGlobal einen Block nicht verwalteten Speichers zu und erstellen dann eine Span unter 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);
        }
    }
}
Imports System
Imports System.Runtime.InteropServices
Friend Class Program
	Shared Sub Main()
		' Managed array to copy data from
		Dim sourceArray() As Integer = { 1, 2, 3, 4, 5 }
		' Allocate unmanaged memory for the destination data
		Dim destinationPointer As IntPtr = MemoryMarshal.Allocate(Of Integer)(sourceArray.Length)
		Try
			' Create a Span<int> from the source array
			Dim sourceSpan As Span(Of Integer) = sourceArray
			' Create a Span<int> from the allocated unmanaged memory
			Dim destinationSpan As Span(Of Integer) = MemoryMarshal.Cast(Of Integer, 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:")
			For Each value In destinationSpan
				Console.Write($"{value} ")
			Next value
		Finally
			' Deallocate the unmanaged memory when done
			MemoryMarshal.Free(destinationPointer)
		End Try
	End Sub
End Class
VB   C#

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 Spanne aus 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);
    }
}
Imports System
Imports System.Runtime.InteropServices
Friend Class Program
	Shared Sub Main()
		Const bufferSize As Integer = 100
		Dim unmanagedMemory As IntPtr = Marshal.AllocHGlobal(bufferSize)
		' Create a Span from the unmanaged memory
		Dim span As New Span(Of Byte)(unmanagedMemory.ToPointer(), bufferSize)
		' Use unsafe code to work with pointers
		' ref t
'INSTANT VB TODO TASK: C# 'unsafe' code is not converted by Instant VB:
'		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)
	End Sub
End Class
VB   C#

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 Memory oder Spannweite um 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
}
Async Function ProcessDataAsync(ByVal stream As Stream) As Task
	Const bufferSize As Integer = 4096
	Dim buffer(bufferSize - 1) As Byte
	Do
		Dim bytesRead As Integer = Await stream.ReadAsync(buffer.AsMemory())
		If bytesRead = 0 Then
			Exit Do
		End If
		' Process the data using Span without unnecessary copying
		ProcessData(buffer.AsSpan(0, bytesRead))
	Loop
End Function
Private Sub ProcessData(ByVal data As Span(Of Byte))
	' Perform operations on the data
End Sub
VB   C#

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 Span ohne 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
}
Async Function ProcessFileAsync(ByVal filePath As String) As Task
	Const bufferSize As Integer = 4096
	Using fileStream As New FileStream(filePath, FileMode.Open, FileAccess.Read)
		Dim buffer(bufferSize - 1) As Byte
		Do
			Dim bytesRead As Integer = Await fileStream.ReadAsync(buffer.AsMemory())
			If bytesRead = 0 Then
				Exit Do
			End If
			' Process the data using Span without unnecessary copying
			ProcessData(buffer.AsSpan(0, bytesRead))
		Loop
	End Using
End Function
Private Sub ProcessData(ByVal data As Span(Of Byte))
	' Perform operations on the data
End Sub
VB   C#

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 Memory oder Spannweite um 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}");
}
Async Function ProcessDataAsync(ByVal data() As Integer) As Task(Of Integer)
	' Asynchronous processing of data
	Await Task.Delay(1000)
	' Returning the length of the processed data
	Return data.Length
End Function
Async Function Main() As Task
	Dim inputData() As Integer = Enumerable.Range(1, 1000).ToArray()
	' Process the data asynchronously without copying
	Dim processedLength As Integer = Await ProcessDataAsync(inputData.AsMemory())
	Console.WriteLine($"Processed data length: {processedLength}")
End Function
VB   C#

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

IronPDF ist die neueste C# PDF-Bibliothek von Iron 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 seine HTML zu PDF funktion, die 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");
    }
}
Imports IronPdf

Friend Class Program
	Shared Sub Main(ByVal args() As String)
		Dim renderer = New ChromePdfRenderer()

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

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

		' 3. Convert URL to PDF
		Dim url = "http://ironpdf.com" ' Specify the URL
		Dim pdfFromUrl = renderer.RenderUrlAsPdf(url)
		pdfFromUrl.SaveAs("URLToPDF.pdf")
	End Sub
End Class
VB   C#

Einrichtung

IronPDF kann mit dem Befehl NuGet Paketmanager-Konsole oder über den Visual Studio-Paketmanager.

dotnet add package IronPdf
// Or
Install-Package IronPdf
dotnet add package IronPdf
// Or
Install-Package IronPdf
'INSTANT VB TODO TASK: The following line uses invalid syntax:
'dotnet add package IronPdf Install-Package IronPdf
VB   C#

C#-Spanne (Wie es für Entwickler funktioniert): Abbildung 1 - Installieren Sie IronPDF mit dem NuGet Package Manager, indem Sie "ironpdf" in der Suchleiste des NuGet Package Managers 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");
    }
}
Imports System
Friend Class Program
	Shared Sub Main()
		Console.WriteLine("Generating PDF using IronPDF.")
		Dim displayFirstName = "<p>First Name is Joe</p>".AsSpan()
		Dim displayLastName = "<p>First Name is Doe</p>".AsSpan()
		Dim displayAddress = "<p>12th Main, 7Th Cross, New York</p>".AsSpan()
		Dim start = "<!DOCTYPE html>
<html>
<body>".AsSpan()
		Dim [end] = "<!DOCTYPE html>
<html>
<body>"
		Dim content = String.Concat(start, displayFirstName, displayLastName, String.Concat(displayAddress, [end]))
		Dim pdfDocument = New ChromePdfRenderer()
		pdfDocument.RenderHtmlAsPdf(content).SaveAs("span.pdf")
	End Sub
End Class
VB   C#

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. Dieser Schlüssel muss in appsettings.json platziert werden.

"IronPdf.LicenseKey": "your license key"
"IronPdf.LicenseKey": "your license key"
'INSTANT VB TODO TASK: The following line uses invalid syntax:
'"IronPdf.LicenseKey": "your license key"
VB   C#

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

Schlussfolgerung

Spannweite in 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 Span für verschiedene Speichermanipulationsaufgaben sicher und effizient. Zusammen mit IronPDFkann es verwendet werden, um großartige PDF-Dokumente zu erzeugen, ohne Grenzen zu erwarten und zu erreichen.

Zusammen mit dem kostenloser Test für den langfristigen Gebrauch. Um mehr über die Verwendung von IronPDF zu erfahren, besuchen Sie bitte deren dokumentation seite.

< PREVIOUS
C# IDE (Wie es für Entwickler funktioniert)
NÄCHSTES >
Opentelemetry C# (Wie es für Entwickler funktioniert)

Sind Sie bereit, loszulegen? Version: 2024.10 gerade veröffentlicht

Gratis NuGet-Download Downloads insgesamt: 11,308,499 Lizenzen anzeigen >