Skip to content

Portée des variables et passage d'arguments

La portée des variables

La portée (ou scope) d'une variable est la zone du code où cette variable existe et peut être utilisée.

Une variable déclarée à l'intérieur d'une fonction n'existe que dans cette fonction. On dit qu'elle est locale.

Une variable locale :

  • est créée quand on arrive à sa ligne de déclaration
  • est détruite quand la fonction se termine
  • n'est pas accessible depuis une autre fonction
DefinirAge();
AfficherAge();

void DefinirAge()
{
    int age = 20;
    Console.WriteLine(age); // affiche 20
}

void AfficherAge()
{
    // Erreur : age n'existe pas ici, il appartient seulement à DefinirAge
    Console.WriteLine(age);
}

Chaque fonction a ses propres variables. Deux fonctions peuvent avoir une variable du même nom sans que cela crée de conflit.

DefinirNombre();
AfficherNombre();

void DefinirNombre()
{
    int nombre = 5;
    Console.WriteLine(nombre); // affiche 5
}

void AfficherNombre()
{
    int nombre = 10;
    Console.WriteLine(nombre); // affiche 10, aucun lien avec le nombre de DefinirNombre
}

La portée d'un bloc

Une variable déclarée à l'intérieur d'un bloc (if, while, for, etc.) n'existe que dans ce bloc.

if (true)
{
    int resultat = 42;
    Console.WriteLine(resultat);
}

// Erreur : resultat n'existe plus ici, on est sorti du bloc
Console.WriteLine(resultat);

Une variable déclarée avant un bloc reste accessible à l'intérieur de celui-ci.

int total = 0;

for (int i = 0; i < 5; i++)
{
    total = total + i; // total est accessible ici
}

Console.WriteLine(total);

La variable déclarée dans la première partie d'un for (par exemple i dans for (int i = 0; ...)) appartient elle aussi à la portée du bloc de la boucle : elle n'existe plus une fois la boucle terminée.

for (int i = 0; i < 5; i++)
{
    Console.WriteLine(i);
}

// Erreur : i n'existe plus ici, on est sorti de la boucle
Console.WriteLine(i);

La fermeture (closure)

Une fermeture est le mécanisme par lequel une fonction déclarée à l'intérieur d'une autre portée (ici, dans les instructions du programme principal) peut accéder à une variable qui existe déjà dans cette portée, même si cette variable n'est pas passée en paramètre.

int compteur = 0;

AugmenterCompteur();
AugmenterCompteur();
Console.WriteLine(compteur); // affiche 2

void AugmenterCompteur()
{
    compteur = compteur + 1; // accède directement à la variable du programme principal
}

Ici, AugmenterCompteur n'a aucun paramètre et ne retourne rien, mais elle modifie tout de même compteur, car elle a été déclarée dans la même portée que cette variable et en garde l'accès. C'est différent des exemples précédents (age, nombre), où la variable n'existait qu'à l'intérieur d'une autre fonction, et donc ne pouvait pas être capturée.

Le passage d'arguments

Quand on appelle une fonction avec des paramètres, on lui donne des arguments.

Par défaut, en C#, les arguments sont passés par valeur : la fonction reçoit une copie de la valeur, pas la variable elle-même.

int nombre = 5;
DoublerValeur(nombre);
Console.WriteLine(nombre); // affiche encore 5

void DoublerValeur(int valeur)
{
    valeur = valeur * 2; // modifie seulement la copie locale
    Console.WriteLine(valeur); // affiche 10
}

Modifier le paramètre à l'intérieur de la fonction ne change donc jamais la variable d'origine utilisée lors de l'appel.

Le mot-clé out

Le mot-clé out permet à une fonction de faire ressortir un résultat sans utiliser return.

Contrairement au passage par valeur, le paramètre out n'est pas une copie : il pointe vers la même variable que l'argument transmis, donc la fonction peut lui assigner une valeur qui sera visible après l'appel.

La variable n'a pas besoin d'être initialisée avant l'appel, puisque la fonction doit obligatoirement lui donner une valeur.

Le mot-clé out doit être écrit deux fois : devant le paramètre dans la signature de la fonction (out int carre) et devant l'argument lors de l'appel (out resultat). Sans l'un des deux, le code ne compile pas.

int resultat;
CalculerCarre(4, out resultat);
Console.WriteLine(resultat); // affiche 16

void CalculerCarre(int nombre, out int carre)
{
    carre = nombre * nombre;
}

Il est aussi possible de déclarer la variable directement lors de l'appel, sans la déclarer à l'avance :

CalculerCarre(4, out int resultat);
Console.WriteLine(resultat); // affiche 16

out est notamment utilisé par des fonctions comme int.TryParse(texte, out valeur). out est surtout utile lorsqu'une fonction doit retourner plus d'une valeur, puisque return ne permet d'en retourner qu'une seule.

bool succes;
int resultat;
succes = EssayerDiviser(10, 2, out resultat);
Console.WriteLine(succes); // affiche True
Console.WriteLine(resultat); // affiche 5

bool EssayerDiviser(int a, int b, out int quotient)
{
    if (b == 0)
    {
        quotient = 0;
        return false;
    }

    quotient = a / b;
    return true;
}

Résumé

Mode Mot-clé Copie ou référence Initialisation requise avant l'appel
Par valeur (aucun) Copie Oui
Sortie out Référence Non