Computer >> Hướng Dẫn Máy Tính >  >> Lập Trình >> C#

Truyền con trỏ (Pointer) làm tham số phương thức trong C#

C# cho phép sử dụng con trỏ (pointer) trong context unsafe. Truyền con trỏ cho phép thao tác trực tiếp bộ nhớ, hữu ích cho interop, performance critical, hoặc thuật toán thấp cấp.

⚠️ Cảnh báo: Code unsafe bỏ qua an toàn kiểu/bộ nhớ của CLR. Chỉ dùng khi cần thiết (interop, high-perf), bật AllowUnsafeBlocks trong project.

Cú pháp

public unsafe void MethodName(int* ptr) { ... }
  • Method/class/block phải đánh dấu unsafe.
  • Con trỏ khai báo: type* name (ví dụ: int* p).
  • Lấy địa chỉ: &variable.
  • Dereference: *ptr.

Ví dụ: Swap hai số nguyên qua con trỏ

using System;

class Program
{
    // Unsafe method nhận con trỏ
    public unsafe void Swap(int* p, int* q)
    {
        int temp = *p; // Dereference
        *p = *q;
        *q = temp;
    }
    
    public unsafe static void Main()
    {
        // Cần bật AllowUnsafeBlocks trong .csproj:
        // true
        
        Program p = new Program();
        int var1 = 10;
        int var2 = 20;
        
        // fixed: pin object trong memory (GC không di chuyển)
        // int là primitive, không cần fixed, nhưng array/struct cần
        int* x = &var1; // Lấy địa chỉ
        int* y = &var2;
        
        Console.WriteLine($"Before Swap: var1={var1}, var2={var2}");
        p.Swap(x, y);
        Console.WriteLine($"After Swap:  var1={var1}, var2={var2}");
        
        // Ví dụ với array (cần fixed)
        int[] arr = { 1, 2, 3, 4, 5 };
        fixed (int* ptr = arr) // Pin mảng
        {
            Console.WriteLine($"First element via pointer: {*ptr}"); // 1
            Console.WriteLine($"Second element: {*(ptr + 1)}");      // 2
        } // Unpin tự động ở đây
    }
}

Kết quả

Before Swap: var1=10, var2=20
After Swap:  var1=20, var2=10
First element via pointer: 1
Second element: 2

Các khái niệm quan trọng

Khái niệmCú phápMô tả
Khai báo con trỏint* p;Con trỏ đến int
Address-of&varLấy địa chỉ biến (chỉ trong unsafe)
Dereference*pTruy cập giá trị tại địa chỉ
Pointer arithmeticp + 1, p - 1Nhảy kích thước kiểu (sizeof(int)=4 bytes)
Fixed statementfixed (int* p = arr)Pin managed object, ngăn GC move
stackallocint* p = stackalloc int[100]Cấp phát trên stack (nhanh, tự free)

Thay thế an toàn hiện đại (Khuyên dùng)

  • Span<T> / Memory<T>: Safe, bounds-checked, zero-allocation view vào memory.
  • ref struct: Stack-only types.
  • Unsafe class: Unsafe.As<T>(), Unsafe.CopyBlock()... không cần unsafe context.
  • Marshal class cho interop.
// Modern safe swap với ref
public static void Swap(ref int a, ref int b)
{
    int temp = a; a = b; b = temp;
}