C# Span (Geliştiriciler İçin Nasıl Çalışır)
Span C# 7.2'de System ad alanındaki Span yapısının bir parçası olarak tanıtılan bir türdür. Rastgele bellek bölgelerini temsil etmek üzere tasarlanmıştır. Yönetilen heap gibi diziler veya koleksiyonların aksine, Span işaret ettiği yığın belleğine veya bellek bölgesine sahip değildir; Bunun yerine, mevcut bellek blokları üzerinde hafif bir görünüm sağlar. Bu özellik, bellek tamponları ile etkili bir şekilde çalışmanız gerektiğinde, ek yük ve güvensiz kod senaryolarına girmeden, Span'i özellikle güçlü kılar. Bu makalenin ilerleyen bölümlerinde Iron Software tarafından geliştirilen IronPDF kutuphanesinin tanıtımını da göreceğiz.
Span'in Ana Özellikleri
1. Bellek Yönetimi
C#'ta Span, geliştiricilerin geleneksel heap tahsislerine başvurmadan doğrudan bellek ile çalışmasına olanak tanır. Mevcut diziler veya diğer bellek kaynaklarından bellek dilimlerinin oluşturulmasına olanak tanır, bu da ek bellek kopyalarının gerekliliğini ortadan kaldırır.
2. Sıfır-Kopya Soyutlamaları
C# Span'in en belirgin özelliklerinden biri sıfır-kopya soyutlamalarıdır. Verileri çoğaltmak yerine, Span mevcut belleği etkili bir şekilde referans vermenin bir yolunu sağlar. Bu, büyük miktarda verinin kopyalanmasının pratik olmadığında veya maliyetli olduğunda özellikle faydalıdır.
3. İşaretçi Benzeri İşlemler
C# geleneksel olarak yüksek seviyeli, güvenli bir dil olsa da, Span C veya C++ gibi dillerde işaretçilerle çalışmaya benzer düzeyde bir bellek manipülasyonu sunar. Geliştiriciler, C#'ın güvenliğinden ve yönetilen doğasından ödün vermeden işaretçi-benzeri işlemler yapabilirler.
4. Değişmez Doğa
Düşük seviyeli bellek erişimi yeteneklerine rağmen, C# Span değişmez kalır. Bu, belleği manipüle etmesine izin verirken, istem dışı değişiklikleri önleyerek güvenliği sağlar.
Örnek
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);
}
}
}
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);
}
}
}
Imports System
Friend Class Program
Shared 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
ReadOnlySpan
Span değiştirilebilir olup, altındaki verilerin değiştirilmesine izin verirken, ReadOnlySpan belleğin değiştirilemez bir görünümünü sunar. Bellek bölgesine yalnızca okunur bir arayüz sağlar, bu da veriyi değiştirmeye gerek olmadığında okunması gereken senaryolar için uygundur.
İşte bazı önemli noktalar.
1. Salt Okunur Görünüm
Adından da anlaşıldığı gibi, ReadOnlySpan belleğin bir bloğunun salt okunur görünümünü oluşturmanıza olanak tanır. Bu, ReadOnlySpan üzerinden öğeleri değiştiremeyeceğiniz anlamına gelir.
2. Bellek Temsili
Span gibi, ReadOnlySpan da işaret ettiği belleği sahiplenmez. Mevcut belleğe referans verir ve dizilere, yığından tahsis edilen belleğe veya yerel belleğe işaret edebilir.
3. Performans Yararları
Span gibi, ReadOnlySpan da özellikle büyük miktarda veri ile çalışırken geleneksel koleksiyon türlerine kıyasla daha iyi performans sunabilir, çünkü kopyalama ihtiyaçını azaltır.
4. Sınır Kontrolü Yok
Span ile olduğu gibi, ReadOnlySpan de sınır kontrolü yapmaz. Operasyonların, altta yatan bellek sınırları içinde kalmasını sağlamak geliştiricinin sorumluluğundadır.
5. Dizi Dilimleme ile Kullanım
ReadOnlySpan dilimlemeyi destekler, bu da orijinal belleğin bir kısmını referans alan alt-dilimler oluşturmanıza imkan tanır.
Örnek
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
ReadOnlySpan oluşturmanın ve onunla çalışmanın birçok farklı yolu vardır. Aşağıda bazı örnekler verilmiştir.
1. ReadOnlySpan String'den Oluşturma
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
2. Alt Dizelerle Çalışma
ReadOnlySpanSlice kullanın
// Example usage of Slice method on ReadOnlySpan<char>
ReadOnlySpan<char> spanFromString = "Sample String".AsSpan();
ReadOnlySpan<char> substringSpan = spanFromString.Slice(7, 6); // Extracts 'String'
// Example usage of Slice method on ReadOnlySpan<char>
ReadOnlySpan<char> spanFromString = "Sample String".AsSpan();
ReadOnlySpan<char> substringSpan = spanFromString.Slice(7, 6); // Extracts 'String'
' Example usage of Slice method on ReadOnlySpan<char>
Dim spanFromString As ReadOnlySpan(Of Char) = "Sample String".AsSpan()
Dim substringSpan As ReadOnlySpan(Of Char) = spanFromString.Slice(7, 6) ' Extracts 'String'
3. Bir Yönteme Alt Dize Geçirme
ReadOnlySpan
void ProcessSubstringfromReadOnlySpan(ReadOnlySpan<char> substring)
{
// Perform operations on the substring
}
// Usage
ReadOnlySpan<char> spanFromString = "Sample String".AsSpan();
ProcessSubstringfromReadOnlySpan(spanFromString.Slice(7, 6));
void ProcessSubstringfromReadOnlySpan(ReadOnlySpan<char> substring)
{
// Perform operations on the substring
}
// Usage
ReadOnlySpan<char> spanFromString = "Sample String".AsSpan();
ProcessSubstringfromReadOnlySpan(spanFromString.Slice(7, 6));
Private Sub ProcessSubstringfromReadOnlySpan(ByVal substring As ReadOnlySpan(Of Char))
' Perform operations on the substring
End Sub
' Usage
Private spanFromString As ReadOnlySpan(Of Char) = "Sample String".AsSpan()
ProcessSubstringfromReadOnlySpan(spanFromString.Slice(7, 6))
4. Bir String İçinde Arama
Bir dizi içinde arama yapmak için ReadOnlySpanIndexOf().
ReadOnlySpan<char> stringSpan = "Hello, World!".AsSpan();
int index = stringSpan.IndexOf('W');
Console.WriteLine(index); // Outputs: 7
ReadOnlySpan<char> stringSpan = "Hello, World!".AsSpan();
int index = stringSpan.IndexOf('W');
Console.WriteLine(index); // Outputs: 7
Dim stringSpan As ReadOnlySpan(Of Char) = "Hello, World!".AsSpan()
Dim index As Integer = stringSpan.IndexOf("W"c)
Console.WriteLine(index) ' Outputs: 7
5. Bellek Haritalı Dosyalar Kullanma
ReadOnlySpan
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);
}
}
}
}
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);
}
}
}
}
Imports System
Imports System.IO.MemoryMappedFiles
Friend Class Program
Private Shared Sub ProcessData(ByVal data As ReadOnlySpan(Of Byte))
' Process data directly from the memory-mapped file
End Sub
Shared Sub Main()
Using memmf = MemoryMappedFile.CreateFromFile("data.bin")
Using accessor = memmf.CreateViewAccessor()
Dim buffer(accessor.Capacity - 1) As Byte
accessor.ReadArray(0, buffer, 0, buffer.Length)
Dim dataSpan As New ReadOnlySpan(Of Byte)(buffer)
ProcessData(dataSpan)
End Using
End Using
End Sub
End Class
6. Verimli String Manipülasyonu
ReadOnlySpan
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
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
Dim newSpan As Span(Of Char) = New Char(5){}
Dim spanFromString As ReadOnlySpan(Of Char) = "Sample String".AsSpan().Slice(7, 6)
spanFromString.CopyTo(newSpan)
Console.WriteLine(New String(newSpan)) ' Outputs: String
7. API'lere Alt Dize Geçirme
Karakter spanleri üzerinde çalışan harici kütüphaneler veya API'lerle çalışırken.
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));
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));
Private Sub ExternalApiMethod(ByVal data As ReadOnlySpan(Of Char))
' Call the external API with the character span
End Sub
' Usage
Private spanFromString As ReadOnlySpan(Of Char) = "Sample String".AsSpan()
ExternalApiMethod(spanFromString.Slice(7, 6))
ReadOnlySpan
Span Sınırlamaları
C#'ta Span çok avantajlı ve güçlü bir özellik olmasına rağmen, ardışık ve ardışık olmayan bellek bağlamında belirli sınırlamaları ve dikkate alınması gereken hususları vardır. Bu sınırlamaları inceleyelim:
1. Bitişik Bellek Tamponları
1.1 Otomatik Bellek Yönetimi Yok
Span işaret ettiği belleği yönetmez. Bu, altında yatan yönetilen bellek serbest bırakılır veya kapsam dışına çıkarsa, Span kullanmanın tanımsız davranış veya potansiyel çöküşlere yol açacağı anlamına gelir. Geliştiriciler, bir Span kullanırken altında yatan belleğin hala geçerli olduğunu garanti etmelidir.
1.2 Çöp Toplama Yok
Span belleği sahiplenmediği için çöp toplanmasına tabi değildir. Bu nedenle, yığın atanan bellek veya Span 'nin kendisinden daha kısa bir ömre sahip bellek ile çalışırken dikkatli olmanız gerekmektedir.
1.3 Sınır Kontrolü Devre Dışı
Span ve ReadOnlySpan varsayılan olarak sınır kontrolü yapmaz. Bu, dikkatli kullanılmazsa geçersiz bellek konumlarına erişmeye yol açabilir. Geliştiriciler, bir Span üzerindeki işlemlerin altındaki belleğin sınırları içinde kaldığından emin olmalıdır.
1.4 Ardışık Olmayan Bellek için Destek Yok
Span bitişik bellekle çalışmak üzere tasarlanmıştır. Bitişik olmayan belleğiniz varsa veya daha karmaşık veri yapıları temsil etmeniz gerekiyorsa, Span en uygun seçim olmayabilir.
1.5 Tüm İşlemler Desteklenmiyor
Span dilimleme, indeksleme ve yineleme gibi birçok yaygın işlemi desteklerken, tüm işlemleri desteklemez. Örneğin, bir Span 'i yeniden boyutlandıramazsınız ve altındaki belleğin uzunluğunu değiştirmeyi içeren belirli işlemler izin verilmez.
1.6 Sınırlı Platform Uyumluluğu
Span .NET Standard ve .NET Core'un bir parçası olsa da, tüm platformlarda veya ortamlarda mevcut olmayabilir. Kodunuzda kullanmayı planlıyorsanız, hedef platformunuzun Span 'yi desteklediğinden emin olmak çok önemlidir.
2. Ardışık Olmayan Bellek Tamponları
2.1 Ardışık Olmayan Bellek için Sınırlı Destek
ReadOnlySpan esas olarak bitişik bellek blokları veya tamponlarla sorunsuz çalışacak şekilde tasarlanmıştır. Bellek bölgelerinde boşluklar olan ardışık olmayan bellek tamponları veya yapıları içeren senaryolar için en uygun seçenek olmayabilir.
2.2 Yapısal Sınırlamalar
Bitişik olmayan belleğe dayanan belirli veri yapıları veya senaryolar, ReadOnlySpan ile uyumlu olmayabilir. Örneğin, bağlanmış listeler veya grafik yapıları gibi veri yapıları, ReadOnlySpan'nin bitişik bellek gereksinimi nedeniyle çok uygun olmayabilir.
2.3 Karmaşık İşaretçi İşlemleri
Özellikle karmaşık gösterici aritmetiği gerektiren bitişik olmayan bellek içeren durumlarda, ReadOnlySpan C++ gibi dillerdeki ham göstericilerin sağladığı aynı düşük seviyeli kontrol ve esnekliği sunmayabilir. Bu tür durumlarda, işaretçilerle güvensiz kod kullanılması daha uygun olabilir.
2.4 Bazı API'lerde Doğrudan Destek Yok
Bitişik bellek gibi, ReadOnlySpan tarafından temsil edilen bitişik olmayan belleği doğrudan destekleyebilecek tüm API'lerin veya kütüphanelerin olmayabileceğini not etmek önemlidir. Bu gibi senaryolara uyum sağlamak, uyumluluğu sağlamak için ek ara adımlar veya dönüşümler gerektirebilir.
Span ve Yönetilmeyen Bellek
C#'ta, Span, bellekle ilgili işlemleri kontrollü ve verimli bir şekilde gerçekleştirmek için yönetilmeyen bellekle etkili bir şekilde kullanılabilir. Yönetilmeyen bellek, .NET çalışma zamanının çöp toplayıcısı tarafından yönetilmeyen belleği ifade eder ve genellikle yerel bellek tahsisleri ve tahliyeleri kullanmayı içerir. C#'ta yönetilmeyen bellek ile Span nasıl kullanılabilir.
Yönetilmeyen Bellek Tahsisi
Yönetilmeyen belleği tahsis etmek için System.Runtime.InteropServices.MemoryMarshal sınıfını kullanabilirsiniz. Marshal.AllocHGlobal yöntemi bellek tahsis eder ve tahsis edilen bloğa bir işaretçi döndürür. Tahsis edilen bellek veya bellek adresi, unmanagedMemory işaretçisi içinde tutulur ve okuma-yazma erişimine sahip olacaktır. Bellek bölgeleri ardışık bir şekilde kolayca erişilebilir.
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
Yukarıdaki kaynak kodunda, Marshal.AllocHGlobal kullanarak yönetilmeyen bellek bloğu ayırırız ve ardından yönetilmeyen bellekten elde edilen göstericiyi kullanarak bir Span<byte> oluştururuz. Bu, tanıdık Span API'sini kullanarak yönetilmeyen bellekle çalışmamıza olanak tanır. Yönetilmeyen bellekle çalışırken, belleğin tahsisi ve serbest bırakılmasından sorumlu olduğunuzu unutmamak önemlidir.
Yönetilmeyen Belleğe Veri Kopyalama ve Yönetilmeyen Bellekten Veri Kopyalama
Span, yönetilen bellek ile yönetilmeyen bellek arasında verileri verimli bir şekilde kopyalamak için Slice, CopyTo ve ToArray gibi yöntemler sağlar.
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);
}
}
}
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);
}
}
}
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 = Marshal.AllocHGlobal(sourceArray.Length * Len(New Integer()))
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 New Span(Of Integer)(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:")
For Each value In destinationSpan
Console.Write($"{value} ")
Next value
Finally
' Deallocate the unmanaged memory when done
Marshal.FreeHGlobal(destinationPointer)
End Try
End Sub
End Class
Bu örnekte:
Marshal.AllocHGlobalhedef veri için yönetilmeyen bellek tahsis eder.new Span<int>(destinationPointer.ToPointer(), sourceArray.Length), tahsis edilen yönetilmeyen bellekten birSpan<int>oluşturur.sourceSpan.CopyTo(destinationSpan)yöntemi, veriyi yönetilen diziden yönetilmeyen belleğe kopyalar.- Hedef bellekteki değerler, kopyalama işlemini doğrulamak için yazdırılır.
Marshal.FreeHGlobal(destinationPointer)yöntemi, iş bittiğinde yönetilmeyen belleği ayırmak için kullanılır.
Güvensiz Kod Kullanımı
Yönetilmeyen bellekle uğraşırken işaretçilerle beraber güvensiz kod da kullanabilirsiniz. Bu tür durumlarda, Unsafe.AsPointer() yöntemini kullanarak Span'den bir işaretçi alabilirsiniz.
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);
}
}
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);
}
}
Imports System
Imports System.Runtime.InteropServices
Imports System.Runtime.CompilerServices
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
'INSTANT VB TODO TASK: C# 'unsafe' code is not converted by Instant VB:
' 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)
End Sub
End Class
Bu örnekte, Span'den bir işaretçi almak için Unsafe.AsPointer yöntemini kullanıyoruz. Bu, doğrudan işaretçilerle ilgilenirken güvensiz kod kullanmamıza izin verir.
Yönetilmeyen bellekle çalışırken, bellek sızıntılarını önlemek için tahsis ve serbest bırakmayı düzgün bir şekilde yönetmenin önemli olduğunu unutmayın. Her zaman Marshal.FreeHGlobal() gibi uygun yöntemler kullanarak yönetilmeyen belleği serbest bırakın. Ek olarak, güvensiz kod kullanırken dikkatli olun, çünkü uygun şekilde ele alınmadığında potansiyel güvenlik riskleri doğurabilir.
Span ve Asenkron Yöntem Çağrıları
C#'ta asenkron yöntem çağrılarıyla beraber Span kullanmak, özellikle büyük miktarda veri veya I/O işlemleriyle uğraşırken güçlü bir kombinasyondur. Amaç, verilerin gereksiz kopyalanması olmadan asenkron işlemleri verimli bir şekilde gerçekleştirmektir. Asenkron senaryolarda Span'den nasıl yararlanabileceğinizi inceleyelim:
1. Asenkron I/O İşlemleri:
Asenkron I/O işlemleri ile çalışırken, örneğin bir akışa veri okuma veya yazma gibi, ek tamponlar oluşturmadan verimli bir şekilde çalışmak için Memory veya Span kullanabilirsiniz.
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
}
}
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
}
}
Imports System
Imports System.IO
Imports System.Threading.Tasks
Friend Class Program
Private Shared 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 Shared Sub ProcessData(ByVal data As Span(Of Byte))
' Perform operations on the data
End Sub
End Class
Bu örnekte, ReadAsync yöntemi, veriyi akıştan asenkron olarak tampon içine okur. Daha sonra, ProcessData yöntemi, veriyi başka bir tampona kopyalamanızı gerektirmeden doğrudan Span
2. Asenkron Dosya İşlemleri:
I/O işlemlerine benzer şekilde, asenkron dosya işlemleriyle uğraşırken, ek kopyalamadan kaçınmak için veriyi verimli bir şekilde işlemek üzere Span kullanabilirsiniz.
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
}
}
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
}
}
Imports System
Imports System.IO
Imports System.Threading.Tasks
Friend Class Program
Private Shared 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 Shared Sub ProcessData(ByVal data As Span(Of Byte))
' Perform operations on the data
End Sub
End Class
Burada, ReadAsync yöntemi, veriyi dosya akışından tampon içine okur ve ProcessData yöntemi, veriyi doğrudan Span
3. Asenkron Görev İşleme:
Asenkron görevlerle çalışırken veri üreten veya tüketen, gereksiz kopyalamayı önlemek için Memory veya Span kullanabilirsiniz.
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}");
}
}
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}");
}
}
Imports System
Imports System.Linq
Imports System.Threading.Tasks
Friend Class Program
Private Shared 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
Shared 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
End Class
Bu örnekte, ProcessDataAsync yöntemi veriyi asenkron olarak işler ve ek kopyalar gerektirmeden işlenen verinin uzunluğunu döndürür.
IronPDF'i Tanıtma
IronPDF kutuphanesi genel bakış Iron Software tarafından geliştirilen ve C# kodu kullanarak dinamik bir şekilde güzel PDF belgeleri oluşturmak için kullanılan en yeni C# PDF kutuphanesidir. IronPDF, HTML'den PDF oluşturmak, HTML içeriğini PDF'ye dönüştürmek, PDF dosyalarını birleştirmek veya bölmek gibi çeşitli özellikler sunar.
IronPDF'nin ana özelliği, düzenleri ve stilleri koruyan HTML to PDF işlevselliğidir. Web içeriğinden PDF'ler oluşturabilir, bu da onu raporlar, faturalar ve belgeler için harika yapar. Bu araç, HTML dosyalarını, URL'leri ve HTML dizgilerini PDF dosyalarına dönüştürmeyi destekler.
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
Kurulum
IronPDF, IronPDF için NuGet paket yöneticisi konsolu veya Visual Studio paket yöneticisi kullanılarak yüklenebilir.
dotnet add package IronPdf // Or Install-Package IronPdf

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");
}
}
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");
}
}
Imports System
Imports IronPdf
Friend Class Program
Shared Sub Main()
Console.WriteLine("Generating PDF using IronPDF.")
Dim displayFirstName = "<p>First Name is Joe</p>".AsSpan()
Dim displayLastName = "<p>Last Name is Doe</p>".AsSpan()
Dim displayAddress = "<p>12th Main, 7Th Cross, New York</p>".AsSpan()
Dim start = "<html><body>".AsSpan()
Dim [end] = "</body></html>".AsSpan()
Dim content = String.Concat(start.ToString(), displayFirstName.ToString(), displayLastName.ToString(), displayAddress.ToString(), [end].ToString())
Dim pdfDocument = New ChromePdfRenderer()
pdfDocument.RenderHtmlAsPdf(content).SaveAs("span.pdf")
End Sub
End Class
Bu örnekte, bir PDF belgesi oluşturmak için Span ve IronPDF kullanıyoruz.
Çıktı:

Oluşturulan PDF:

Lisanslama (Ücretsiz Deneme Mevcut)
IronPDF lisans bilgileri. Bu anahtar appsettings.json dosyasına yerleştirilmelidir.
"IronPdf.LicenseKey": "your license key"
Deneme lisansı almak için e-posta adresinizi sağlayın.
Sonuç
C#'ta Span, performans ve esneklik açısından faydalar sunarak bellekle çalışmanın güçlü ve etkili bir yolunu sağlar. Sahip olmayan, ardışık yapısı, bellek tahsislerini ve kopyalamayı minimize etmenin önemli olduğu senaryolar için özellikle uygun hale getirir. Span'den yararlanarak, geliştiriciler dizi manipülasyonundan yüksek performanslı sayısal işlemlere kadar uygulamaların bir çeşidinde daha iyi performans elde edebilirler. Özelliklerini anlamak ve sınırlılıklarını göz önünde bulundurmak suretiyle, geliştiriciler Span 'yi çeşitli bellek manipülasyon görevleri için güvenli ve etkili bir şekilde kullanabilirler. IronPDF kutuphanesi genel bakış ile birlikte, awesome PDF belgeleri tekrar deneme veya yield sınırları olmadan oluşturmak için kullanılabilir.
Lütfen IronPDF'nin Hızlı Başlangıç Dokümantasyon Sayfası sayfasını ziyaret edin.
Sıkça Sorulan Sorular
C# dilinde Span nedir ve neden önemlidir?
Span, C# 7.2'de tanitilan ve bellegin bitisik bir bolgesini temsil eden bir turdur. Önemlidir cunku geliştiricilerin yigin tahsislerinin ek yukunu ortadan kaldirarak dusuk seviyeli bellek işlemlerini verimli bir şekilde yapmalarini saglar; bu, C#'in güvenligi ve performansini korur.
C# dilinde Span bellek manipulasyonunu nasıl optimize eder?
Span, bellegin uzerinde sifir kopya soyutlama saglayarak ve mevcut bellek bloklarina veri kopyalamadan referans verebilmeye izin vererek bellek manipulasyonu optimize eder. Bu, özellikle büyük veri hacimlerini işleyen uygulamalarda performans iyilestirmelerine yol acar.
Span ile ReadOnlySpan arasindaki fark nedir?
Span, bellegin değiştirilebilir bir gorunumunu sunarak değişikliklere izin verirken, ReadOnlySpan sadece okuma gorunumu sunar. ReadOnlySpan, performans faydalari ve veri butunlugunu saglarken degismemesi gereken veriler için kullanilir.
C# dilinde Span yönetilmeyen bellekle kullanilabilir mi?
Evet, Span, yönetilmeyen bellege bir göstergeden span oluşturarak yönetilmeyen bellek ile kullanilabilir. Bu, Marshal.AllocHGlobal ve Marshal.FreeHGlobal gibi yöntemler kullanilarak bellegin doğru bir şekilde tahsis edilmesini ve serbest birakilmasini saglarken belleğin doğrudan manipulasyonuna izin verir.
IronPDF, PDF uretimi için Span ile nasıl entegre olur?
IronPDF, bellek verimliligini yöneterek ve gereksiz tahsislerden kacinarak Span ile çalışarak dinamik olarak PDF uretimi yapabilir. Bu entegrasyon, geliştiricilerin web iceriginden PDF belgeleri oluşturmasini iyilestirilmis bir performansla saglar.
Bellek yönetimi için Span kullanmanin sinirlamalari nelerdir?
Span kullanmanin sinirlamalari, bitisik bellek gerektirmesi, otomatik bellek yönetimi ve cöp toplama desteğinin olmamasi ve bitisik olmayan bellek için destek sunmamasi gibi konulardir. Geliştiriciler, bellek gecerliligini ve sinirlarini manuel olarak saglamalidir.
C#'de PDF manipulasyonu için IronPDF nasıl yüklenir?
IronPDF, bir C# projesine NuGet package manager'ı kullanarak yüklenebilir. dotnet add package IronPdf veya Install-Package IronPdf gibi komutlar kullanarak projenize ekleyebilirsiniz.
Span kullanmanin string manipulasyonu için faydalari nelerdir?
Span, bellek tahsislerini ve kopyalamalari en aza indirerek verimli string manipulasyonunu saglar. Bu, büyük miktarda string verisi işlenen performans gerektiren kodda özellikle faydalidir.
IronPDF için bir deneme sürümü mevcut mu?
Evet, IronPDF, deneme lisansı sunmaktadır ve e-postanızı sağlayarak elde edebilirsiniz. Deneme lisansı anahtarı, kütüphaneyi kullanmak için appsettings.json dosyasına yerleştirilmelidir.
Span asenkron yöntem cagrilarinda kullanilabilir mi?
Evet, Span, verileri verimli bir şekilde işlemede kullanilabilir, gereksiz kopyalamalardan kacinabilir. Bu, Memory veya Span'den yararlanarak I/O işlemleri ve dosya işleme için özellikle faydalidir.




