istruzione fixed: bloccare una variabile per le operazioni del puntatore

L'istruzione fixed impedisce al garbage collector di spostare una variabile spostabile e dichiara un puntatore per tale variabile. L'indirizzo di una variabile fissa o bloccata non cambia durante l'esecuzione dell'istruzione. È possibile usare il puntatore dichiarato solo all'interno dell'istruzione fixed corrispondente. Il puntatore dichiarato è di sola lettura e non può essere modificato:

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.

Nota

È possibile usare l'istruzione fixed solo in un contesto non sicuro. Il codice che contiene blocchi non sicuri deve essere compilato con l'opzione AllowUnsafeBlocks del compilatore.

È possibile inizializzare il puntatore dichiarato come segue:

  • Con una matrice, come illustrato nell'esempio all'inizio di questo articolo. Il puntatore inizializzato contiene l'indirizzo del primo elemento della matrice.

  • Con un indirizzo di una variabile. Usare l'operatore address-of&, come illustrato nell'esempio seguente:

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

    I campi oggetto sono un altro esempio di variabili spostabili che possono essere bloccate.

    Quando il puntatore inizializzato contiene l'indirizzo di un campo oggetto o di un elemento di matrice, l'istruzione fixed garantisce che il garbage collector non ricollochi o smaltisca l'istanza dell'oggetto contenente durante l'esecuzione del corpo dell'istruzione

  • Con l'istanza del tipo che implementa un metodo denominato GetPinnableReference. Tale metodo deve restituire una variabile refdi un tipo non gestito. I tipi .NET System.Span<T> e System.ReadOnlySpan<T> usano questo criterio. È possibile aggiungere istanze di span, come illustrato nell'esempio seguente:

    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
        }
    }
    

    Per altre informazioni, vedere le informazioni di riferimento sull'API Span<T>.GetPinnableReference().

  • Con una stringa, come illustrato nell'esempio seguente:

    unsafe
    {
        var message = "Hello!";
        fixed (char* p = message)
        {
            Console.WriteLine(*p);  // output: H
        }
    }
    
  • Con un buffer a dimensione fissa.

È possibile allocare memoria nello stack, dove non è soggetta a garbage collection e pertanto non deve essere bloccata. A tale scopo, usare un'espressione stackalloc.

Inoltre, è possibile usare la parola chiave fixed per dichiarare un buffer a dimensione fissa.

Specifiche del linguaggio C#

Per altre informazioni, vedere le sezioni seguenti delle specifiche del linguaggio C#:

Vedi anche