C# Language peu sûr


Exemple

Le mot clé unsafe peut être utilisé dans les déclarations de type ou de méthode ou pour déclarer un bloc en ligne.

Le but de ce mot clé est de permettre l'utilisation du sous - ensemble non sécurisé de C # pour le bloc en question. Le sous-ensemble non sécurisé inclut des fonctionnalités telles que les pointeurs, l'allocation de pile, les tableaux de type C, etc.

Le code dangereux n'est pas vérifiable et c'est pourquoi son utilisation est déconseillée. La compilation de code non sécurisé nécessite de passer un commutateur au compilateur C #. En outre, le CLR exige que l'assembly en cours d'exécution soit totalement sécurisé.

Malgré ces limitations, le code non sécurisé a des utilisations valides pour rendre certaines opérations plus performantes (par exemple, indexation de tableaux) ou plus simples (par exemple, interopérer avec certaines bibliothèques non gérées).

Comme exemple très simple

// compile with /unsafe
class UnsafeTest
{
   unsafe static void SquarePtrParam(int* p)
   {
      *p *= *p; // the '*' dereferences the pointer.
      //Since we passed in "the address of i", this becomes "i *= i"
   }

   unsafe static void Main()
   {
      int i = 5;
      // Unsafe method: uses address-of operator (&):
      SquarePtrParam(&i); // "&i" means "the address of i". The behavior is similar to "ref i"
      Console.WriteLine(i); // Output: 25
   }
}

En travaillant avec des pointeurs, nous pouvons changer les valeurs des emplacements de mémoire directement, plutôt que de devoir les adresser par leur nom. Notez que cela nécessite souvent l'utilisation du mot clé fixed pour éviter toute corruption de mémoire car le ramasse-miettes déplace les objets (sinon, vous risquez d'obtenir l' erreur CS0212 ). Comme une variable qui a été "corrigée" ne peut pas être écrite, nous devons souvent avoir un deuxième pointeur qui pointe vers le même emplacement que le premier.

void Main()
{
    int[] intArray = new int[] { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10};

    UnsafeSquareArray(intArray);
    foreach(int i in intArray)
        Console.WriteLine(i);
}

unsafe static void UnsafeSquareArray(int[] pArr)
{
    int len = pArr.Length;

    //in C or C++, we could say
    // int* a = &(pArr[0])
    // however, C# requires you to "fix" the variable first 
    fixed(int* fixedPointer = &(pArr[0]))
    {
        //Declare a new int pointer because "fixedPointer" cannot be written to.
        // "p" points to the same address space, but we can modify it
        int* p = fixedPointer;

        for (int i = 0; i < len; i++)
        {
            *p *= *p; //square the value, just like we did in SquarePtrParam, above
            p++;      //move the pointer to the next memory space.
                      // NOTE that the pointer will move 4 bytes since "p" is an
                      // int pointer and an int takes 4 bytes

            //the above 2 lines could be written as one, like this:
            // "*p *= *p++;"
        }
    }
}

Sortie:

1
4
9
16
25
36
49
64
81
100

unsafe permet également l'utilisation de stackalloc qui allouera de la mémoire sur la pile comme _alloca dans la bibliothèque d'exécution C. Nous pouvons modifier l'exemple ci-dessus pour utiliser stackalloc comme suit:

unsafe void Main()
{
    const int len=10;
    int* seedArray = stackalloc int[len];
    
    //We can no longer use the initializer "{ 1, 2, 3, 4, 5, 6, 7, 8, 9, 10}" as before.
    // We have at least 2 options to populate the array. The end result of either
    // option will be the same (doing both will also be the same here).

    //FIRST OPTION:
    int* p = seedArray; // we don't want to lose where the array starts, so we
                        // create a shadow copy of the pointer
    for(int i=1; i<=len; i++)
        *p++ = i;
    //end of first option

    //SECOND OPTION:
    for(int i=0; i<len; i++)
        seedArray[i] = i+1;
    //end of second option

    UnsafeSquareArray(seedArray, len);
    for(int i=0; i< len; i++)
        Console.WriteLine(seedArray[i]);
}

//Now that we are dealing directly in pointers, we don't need to mess around with
// "fixed", which dramatically simplifies the code
unsafe static void UnsafeSquareArray(int* p, int len)
{
    for (int i = 0; i < len; i++)
        *p *= *p++;
}

(La sortie est la même que ci-dessus)