fixed, instruction (référence C#)fixed Statement (C# Reference)

L’instruction fixed empêche le récupérateur de mémoire de déplacer une variable mobile.The fixed statement prevents the garbage collector from relocating a movable variable. L’instruction fixed est uniquement autorisée dans un contexte unsafe.The fixed statement is only permitted in an unsafe context. Vous pouvez également utiliser le mot clé fixed pour créer des mémoires tampons de taille fixe.You can also use the fixed keyword to create fixed size buffers.

L’instruction fixed définit un pointeur vers une variable managée et épingle cette variable pendant l’exécution de l’instruction.The fixed statement sets a pointer to a managed variable and "pins" that variable during the execution of the statement. Les pointeurs vers des variables managées ne sont utiles que dans un contexte fixed.Pointers to movable managed variables are useful only in a fixed context. Sans contexte fixed, le garbage collection peut déplacer les variables de manière imprévisible.Without a fixed context, garbage collection could relocate the variables unpredictably. Le compilateur C# permet seulement d’assigner un pointeur à une variable managée dans une instruction fixed.The C# compiler only lets you assign a pointer to a managed variable in a fixed statement.

class Point 
{ 
    public int x;
    public int y; 
}

unsafe private static void ModifyFixedStorage()
{
    // Variable pt is a managed variable, subject to garbage collection.
    Point pt = new Point();

    // Using fixed allows the address of pt members to be taken,
    // and "pins" pt so that it is not relocated.

    fixed (int* p = &pt.x)
    {
        *p = 1;
    }
}

Vous pouvez initialiser un pointeur à l’aide d’un tableau, d’une chaîne, d’un tampon de taille fixe ou de l’adresse d’une variable.You can initialize a pointer by using an array, a string, a fixed-size buffer, or the address of a variable. L’exemple suivant montre l’utilisation des adresses de variables, des tableaux et des chaînes :The following example illustrates the use of variable addresses, arrays, and strings:

Point point = new Point();
double[] arr = { 0, 1.5, 2.3, 3.4, 4.0, 5.9 };
string str = "Hello World";

// The following two assignments are equivalent. Each assigns the address
// of the first element in array arr to pointer p.

// You can initialize a pointer by using an array.
fixed (double* p = arr) { /*...*/ }

// You can initialize a pointer by using the address of a variable. 
fixed (double* p = &arr[0]) { /*...*/ }

// The following assignment initializes p by using a string.
fixed (char* p = str) { /*...*/ }

// The following assignment is not valid, because str[0] is a char, 
// which is a value, not a variable.
//fixed (char* p = &str[0]) { /*...*/ } 

À compter de C# 7.3, l’instruction fixed s’applique à d’autres types au-delà des tableaux, chaînes, mémoires tampons de taille fixe ou variables non managées.Starting with C# 7.3, the fixed statement operates on additional types beyond arrays, strings, fixed size buffers, or unmanaged variables. Tout type qui implémente une méthode nommée GetPinnableReference peut être épinglé.Any type that implements a method named GetPinnableReference can be pinned. GetPinnableReference doit retourner une variable ref d’un type non managé.The GetPinnableReference must return a ref variable of an unmanaged type. Les types .NET System.Span<T> et System.ReadOnlySpan<T> introduits dans .NET Core 2.0 utilisent ce modèle et peuvent être épinglés.The .NET types System.Span<T> and System.ReadOnlySpan<T> introduced in .NET Core 2.0 make use of this pattern and can be pinned. Ceci est illustré dans l'exemple suivant :This is shown in the following example:

unsafe private static void FixedSpanExample()
{
    int[] PascalsTriangle = {
                  1,
                1,  1,
              1,  2,  1,
            1,  3,  3,  1,
          1,  4,  6,  4,  1,
        1,  5,  10, 10, 5,  1
    };

    Span<int> RowFive = new Span<int>(PascalsTriangle, 10, 5);

    fixed (int* ptrToRow = RowFive)
    {
        // Sum the numbers 1,4,6,4,1
        var sum = 0;
        for (int i = 0; i < RowFive.Length; i++)
        {
            sum += *(ptrToRow + i);
        }
        Console.WriteLine(sum);
    }
}

Si vous créez des types qui doivent être inclus dans ce modèle, consultez Span<T>.GetPinnableReference() pour obtenir un exemple d’implémentation du modèle.If you are creating types that should participate in this pattern, see Span<T>.GetPinnableReference() for an example of implementing the pattern.

Plusieurs pointeurs peuvent être initialisés dans une instruction s’ils sont tous du même type :Multiple pointers can be initialized in one statement if they are all the same type:

fixed (byte* ps = srcarray, pd = dstarray) {...}

Pour initialiser des pointeurs de types différents, imbriquez des instructions fixed, comme indiqué dans l’exemple suivant.To initialize pointers of different types, simply nest fixed statements, as shown in the following example.

fixed (int* p1 = &point.x)
{
    fixed (double* p2 = &arr[5])
    {
        // Do something with p1 and p2.
    }
}

Une fois que le code de l’instruction est exécuté, toutes les variables épinglées sont libérées et soumises au garbage collection.After the code in the statement is executed, any pinned variables are unpinned and subject to garbage collection. Par conséquent, ne pointez pas vers ces variables en dehors de l’instruction fixed.Therefore, do not point to those variables outside the fixed statement. La portée des variables déclarées dans l’instruction fixed est limitée à cette instruction, ce qui facilite les choses :The variables declared in the fixed statement are scoped to that statement, making this easier:

fixed (byte* ps = srcarray, pd = dstarray)
{
   ...
}
// ps and pd are no longer in scope here.

Les pointeurs initialisés dans des instructions fixed sont des variables en lecture seule.Pointers initialized in fixed statements are readonly variables. Pour modifier la valeur du pointeur, vous devez déclarer une deuxième variable de pointeur et la modifier.If you want to modify the pointer value, you must declare a second pointer variable, and modify that. La variable déclarée dans l’instruction fixed ne peut pas être modifiée :The variable declared in the fixed statement cannot be modified:

fixed (byte* ps = srcarray, pd = dstarray)
{
    byte* pSourceCopy = ps;
    pSourceCopy++; // point to the next element.
    ps++; // invalid: cannot modify ps, as it is declared in the fixed statement.
}

Vous pouvez allouer de la mémoire à la pile, où elle n’est pas soumise au nettoyage de la mémoire et n’a donc pas besoin d’être épinglée.You can allocate memory on the stack, where it is not subject to garbage collection and therefore does not need to be pinned. Pour ce faire, utilisez l’stackallocopérateur.To do that use the stackalloc operator.

spécification du langage C#C# language specification

Pour plus d’informations, consultez la section Instructions fixes de la spécification du langage C#.For more information, see The fixed statement section of the C# language specification.

Voir aussiSee also