Altbilgi içeriğine atla
.NET YARDıM

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
$vbLabelText   $csharpLabel

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
$vbLabelText   $csharpLabel

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
$vbLabelText   $csharpLabel

2. Alt Dizelerle Çalışma

ReadOnlySpan üzerinde Slice 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'
$vbLabelText   $csharpLabel

3. Bir Yönteme Alt Dize Geçirme

ReadOnlySpan öğesini bir yönteme parametre olarak geçirin.

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))
$vbLabelText   $csharpLabel

4. Bir String İçinde Arama

Bir dizi içinde arama yapmak için ReadOnlySpan ile IndexOf().

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
$vbLabelText   $csharpLabel

5. Bellek Haritalı Dosyalar Kullanma

ReadOnlySpan bellek haritalı dosyalarla daha verimli olabilir.

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
$vbLabelText   $csharpLabel

6. Verimli String Manipülasyonu

ReadOnlySpan verimli string manipülasyonu için kullanılabilir.

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
$vbLabelText   $csharpLabel

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))
$vbLabelText   $csharpLabel

ReadOnlySpan, bellek tahsisleri ve kopyalamanın en aza indirilmesi gereken senaryolarda stringlerle daha verimli çalışmanın bir yolunu sağlar. Performans açısından kritik kodları optimize etmek için güçlü bir araçtır ve büyük miktarda string verisi ile uğraşırken özellikle faydalı olabilir.

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
$vbLabelText   $csharpLabel

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
$vbLabelText   $csharpLabel

Bu örnekte:

  • Marshal.AllocHGlobal hedef veri için yönetilmeyen bellek tahsis eder.
  • new Span<int>(destinationPointer.ToPointer(), sourceArray.Length), tahsis edilen yönetilmeyen bellekten bir Span<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
$vbLabelText   $csharpLabel

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
$vbLabelText   $csharpLabel

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 içerisinden işler.

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
$vbLabelText   $csharpLabel

Burada, ReadAsync yöntemi, veriyi dosya akışından tampon içine okur ve ProcessData yöntemi, veriyi doğrudan Span içerisinden işler.

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
$vbLabelText   $csharpLabel

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
$vbLabelText   $csharpLabel

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

C# Span (Geliştiriciler İçin Nasıl Çalışır): Şekil 1 - IronPDF'yi NuGet Paket Yöneticisi arama çubuğuna ironpdf yazarak yükleme

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
$vbLabelText   $csharpLabel

Bu örnekte, bir PDF belgesi oluşturmak için Span ve IronPDF kullanıyoruz.

Çıktı:

C# Span (Geliştiriciler İçin Nasıl Çalışır): Şekil 2 - Konsol Çıktısı

Oluşturulan PDF:

C# Span (Geliştiriciler İçin Nasıl Çalışır): Şekil 3 - PDF Çıktısı

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.

Jacob Mellor, Teknoloji Direktörü @ Team Iron
Chief Technology Officer

Jacob Mellor, Iron Software'in Teknoloji Müdürü ve C# PDF teknolojisinin öncüsü olan vizyoner bir mühendis. Iron Software’in temel kod tabanının ilk geliştiricisi olarak, şirketin ürün mimarisini kuruluşundan bu yana şekillendirdi ve CEO Cameron Rimington ile birlikte NASA, Tesla ve ...

Daha Fazlasını Oku

Iron Destek Ekibi

Haftanın 5 günü, 24 saat çevrimiçiyiz.
Sohbet
E-posta
Beni Ara