OldWiki. Fonctions - skaaj/ensc-support GitHub Wiki

Comme je le disais dans la partie sur les variables, il existe les types valeurs et les types référence. (cf. MSDN)

Les variables de types valeurs sont passés par copie à une fonction. C'est à dire que la fonction appelée va :

  1. Copier votre variable dans une nouvelle variable.
  2. Exécuter son code sur cette nouvelle variable.
  3. Supprimer cette nouvelle variable lorsqu'elle termine (accolade fermante « } »).

Une variable de type référence quant à elle est passée par ... référence. On communique à la fonction qu'on appelle l'endroit où elle se trouve en mémoire. Son fonctionnement est donc :

  1. Créer une nouvelle variable ayant la même référence que celle passée en paramètre (ie. dans l'exemple ci-dessous tableau et tab sont deux variables différentes mais elles pointent vers le même endroit dans la mémoire vive).
  2. Exécuter son code sur cette variable (et donc l'autre étant donnée qu'elles partagent la même valeur en mémoire).
  3. Supprimer cette nouvelle variable lorsqu'elle se termine (mais uniquement la variable, pas l'endroit en mémoire).

Voici un exemple pour mieux comprendre :

static void Main(string[] args)
{
    // Type référence (int, double, struct...)
    int entier = 111;
    Console.WriteLine(entier); // 111
    ChangerEntier(entier);
    Console.WriteLine(entier); // 111

    // Type référence (tableaux, objets)
    int[] tableau = { 1, 1, 1 };
    AfficherTableau(tableau); // 111
    ChangerTableau(tableau);
    AfficherTableau(tableau); // 007

    Console.ReadLine();
}

static void ChangerEntier(int a)
{
    a = 7;
}

static void ChangerTableau(int[] tab)
{
    for (int i = 0; i < tab.Length - 1; i++)
        tab[i] = 0; // ne met que des 0...

    tab[tab.Length - 1] = 7; // ...et un 7 sur la dernière case
}

static void AfficherTableau(int[] tab)
{
    foreach (var entier in tab)
        Console.Write(entier);

    Console.Write(Environment.NewLine); // On revient à la ligne
}

Passage par référence

Imaginons que dans l'exemple précédent nous souhaitions que notre méthode ChangerEntier répercute sa modification dans le main. Un entier étant un type valeur il est par défaut passé par copie. Mais il est possible de spécifier explicitement que l'on souhaite le faire passer par référence en ajoutant le mot clé ref. L'exemple ci-dessous illustre ces propos.

static void Main(string[] args)
{
    string texte = "Bonjour";
            
    Console.WriteLine(texte); // Affiche "Bonjour"
    ChangerTexte(texte);
    Console.WriteLine(texte); // Affiche "Bonjour"
    ChangerTexte(ref texte);
    Console.WriteLine(texte); // Affiche "Aurevoir"

    Console.ReadLine();
}

static void ChangerTexte(string texte)
{
    texte = "Aurevoir";
}

static void ChangerTexte(ref string texte)
{
    texte = "Aurevoir";
}

Il existe également le mot clé out. La différence avec ref est qu'il n'est plus nécessaire d'assigner notre variable au préalable (opérateur « = »). Ajouter le mot clé dit au compilateur que « je m'engage à assigner cette variable avant la fin de la fonction ».
Voici un petit exemple :

static void Main(string[] args)
{
    int variable; // on ne met pas de " = "
    ChangerEntier(ref variable); // ne fonctionne pas
    ChangerEntier(out variable); // fonctionne
}

static void ChangerEntier(ref int a)
{
    a = 7;
}

static void ChangerEntier(out int a)
{
    a = 7;
}