fixed 語句 - 安全地存取變數基礎的記憶體

fixed語句可防止垃圾收集行程重新放置可移動的變數,並宣告該變數的指標。 固定或固定變數的位址不會在語句執行期間變更。 您只能在對應的 fixed 語句內使用宣告的指標。 宣告的指標是唯讀的,無法修改:

unsafe
{
    byte[] bytes = { 1, 2, 3 };
    fixed (byte* pointerToFirst = bytes)
    {
        Console.WriteLine($"The address of the first array element: {(long)pointerToFirst:X}.");
        Console.WriteLine($"The value of the first array element: {*pointerToFirst}.");
    }
}
// Output is similar to:
// The address of the first array element: 2173F80B5C8.
// The value of the first array element: 1.

注意

您只能在不安全的內容中使用 fixed 語句。 包含不安全區塊的程式碼必須使用 AllowUnsafeBlocks 編譯器選項進行編譯。

您可以初始化宣告的指標,如下所示:

  • 使用陣列,如本文開頭的範例所示。 初始化的指標包含第一個陣列專案的位址。

  • 使用變數的位址。 使用 運算子的位址 &,如下列範例所示:

    unsafe
    {
        int[] numbers = { 10, 20, 30 };
        fixed (int* toFirst = &numbers[0], toLast = &numbers[^1])
        {
            Console.WriteLine(toLast - toFirst);  // output: 2
        }
    }
    

    物件欄位是可釘選的可移動變數的另一個範例。

    當初始化的指標包含物件欄位或陣列專案的位址時, fixed 語句會保證垃圾收集行程不會在執行語句主體期間重新放置或處置包含的物件實例。

  • 使用實作名為 GetPinnableReference 之方法之型別的實例。 該方法必須傳回 refUnmanaged 類型的變數。 .NET 類型 System.Span<T>System.ReadOnlySpan<T> 使用此模式。 您可以釘選範圍實例,如下列範例所示:

    unsafe
    {
        int[] numbers = { 10, 20, 30, 40, 50 };
        Span<int> interior = numbers.AsSpan()[1..^1];
        fixed (int* p = interior)
        {
            for (int i = 0; i < interior.Length; i++)
            {
                Console.Write(p[i]);  
            }
            // output: 203040
        }
    }
    

    如需詳細資訊,請參閱 Span<T>.GetPinnableReference() API 參考。

  • 使用字串,如下列範例所示:

    unsafe
    {
        var message = "Hello!";
        fixed (char* p = message)
        {
            Console.WriteLine(*p);  // output: H
        }
    }
    
  • 使用 固定大小緩衝區

您可以在堆疊上配置記憶體,其中不會受到垃圾收集的影響,因此不需要釘選。 若要這樣做,請使用stackalloc 運算式

您也可以使用 fixed 關鍵字來宣告 固定大小的緩衝區

C# 語言規格

如需詳細資訊,請參閱 C# 語言規格的下列幾節:

如需模式型 fixed 語句的相關資訊,請參閱 模式 fixed 型語句 功能提案附注。

另請參閱