Instrucción fija: anclar una variable para las operaciones de puntero
La instrucción fixed
impide que el recolector de elementos no utilizados recoloque una variable desplazable y declare un puntero a esa variable. La dirección de una variable fija (o anclada) no cambia mientras dure la instrucción. El puntero declarado solo se puede usar dentro de la instrucción fixed
correspondiente. El puntero declarado es de solo lectura y no se puede modificar.
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
La instrucción fixed
solo se puede usar en un contexto no seguro. El código que contenga bloques no seguros se tendrá que compilar con la opción del compilador AllowUnsafeBlocks.
El puntero declarado se puede inicializar de las siguientes maneras:
Con una matriz, como se muestra en el ejemplo al principio de este artículo. El puntero inicializado contiene la dirección del primer elemento de la matriz.
Con una dirección de una variable. Use el operador de dirección
&
, como se muestra en el siguiente ejemplo:unsafe { int[] numbers = [10, 20, 30]; fixed (int* toFirst = &numbers[0], toLast = &numbers[^1]) { Console.WriteLine(toLast - toFirst); // output: 2 } }
Los campos de objeto son otro ejemplo de variables desplazables que se pueden anclar.
Cuando el puntero inicializado contiene la dirección de un campo de objeto o un elemento de matriz, la instrucción
fixed
impide que el recolector de elementos no utilizados recoloque o elimine la instancia de objeto contenedor durante la ejecución del cuerpo de la instrucción.Con la instancia del tipo que implementa un método denominado
GetPinnableReference
. Ese método debe devolver una variableref
de un tipo no administrado. Los tipos de .NET System.Span<T> y System.ReadOnlySpan<T> hacen uso de este patrón. Se pueden anclar instancias de intervalo, como se muestra en el siguiente ejemplo: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 } }
Para más información, vea la referencia de API Span<T>.GetPinnableReference().
Con una cadena, como se muestra en el siguiente ejemplo:
unsafe { var message = "Hello!"; fixed (char* p = message) { Console.WriteLine(*p); // output: H } }
Con un búfer de tamaño fijo.
Puede asignar memoria en la pila, donde no está sujeta a la recolección de elementos no utilizados y, por tanto, no necesita anclarse. Para ello, use una expresión stackalloc
.
También puede usar la palabra clave fixed
para declarar un búfer de tamaño fijo.
Especificación del lenguaje C#
Para más información, vea las secciones siguientes de la Especificación del lenguaje C#: