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'istruzioneCon l'istanza del tipo che implementa un metodo denominato
GetPinnableReference
. Tale metodo deve restituire una variabileref
di 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#: