CodeGym /Cours /C# SELF /Modificateurs de paramètres ( ref, out, in)

Modificateurs de paramètres ( ref, out, in)

C# SELF
Niveau 12, Leçon 4
Disponible

1. Introduction

En C#, par défaut, tous les paramètres des méthodes sont passés par valeur, c'est-à-dire qu'une copie arrive dans la méthode, pas l'original.

Mais si le but c'est de modifier une variable externe depuis l'intérieur d'une méthode ? Ou de retourner plusieurs valeurs d'une méthode ? Ou alors, t'as une grosse structure à passer dans une méthode, mais t'as pas envie de copier tout ce "sac sans poignée", tu veux juste passer une référence pour économiser de la mémoire ?

Tout ça, c'est à propos des modificateurs de paramètres. Ils te donnent le contrôle sur le "chemin de transmission" des données entre le code appelant et la méthode.

Types de modificateurs

Modificateur Transmission des données Faut-il initialiser avant l'appel ? Lecture possible à l'intérieur ? Écriture possible à l'intérieur ? Scénarios typiques d'utilisation
ref Dans les deux sens Oui Oui Oui Passer une variable pour lecture et/ou modification
out Seulement vers l'extérieur Non Non (avant affectation) Oui (obligatoire !) Retourner plusieurs valeurs depuis une méthode
in Seulement vers l'intérieur Oui Oui Non Passer de grosses structures en "lecture seule" pour économiser

T'inquiète, on va passer sur chacun d'eux. C'est bien plus simple que ça en a l'air.

2. Modificateur ref : On passe par référence : lecture et écriture

Imagine : tu files une tasse de café à ton pote et tu lui dis — "Tiens, tu peux la boire, la réchauffer, ou même rajouter ce que tu veux dedans". Ton pote peut faire ce qu'il veut avec ce café, et ce qui reste (ou pas) — ça te revient. Voilà comment marche ref.


void DoSomething(ref int x)
{
    x = x + 10; // On modifie le paramètre d'entrée
}
        
Méthode avec un paramètre ref

Pour passer un paramètre en ref, il faut le déclarer avec ce modificateur et aussi l'utiliser lors de l'appel :

int myNumber = 5;
DoSomething(ref myNumber);
Console.WriteLine(myNumber); // affichera 15

Ça doit obligatoirement être une variable, tu peux pas passer une expression par référence. Ce code ne marchera pas :

DoSomething(ref 10);		// ici il faut une variable !
  • Avant l'appel : la variable doit être initialisée (une valeur doit être affectée).
  • Dans la méthode : tu peux lire et modifier la valeur.
  • Après l'appel : les changements sont conservés.

Exemple : On échange les valeurs de deux variables

Parfois, tu veux échanger les valeurs de deux variables. Mais attention : en C#, les types valeurs (genre int) sont passés par valeur par défaut. Ça veut dire que quand tu les passes à une méthode, c'est la valeur qui est copiée, pas la référence à la variable. Pour que la méthode puisse modifier les variables du code appelant, il faut utiliser le mot-clé ref.

Exemple sans ref — ça marche pas :

// Tentative d'échange — ça ne marchera pas
void Swap(int a, int b)
{
    int temp = a;
    a = b;
    b = temp;
}

int x = 10;
int y = 20;
Swap(x, y); // Ce sont des copies de valeurs qui sont passées
Console.WriteLine($"{x}, {y}"); // → 10, 20 — rien n'a changé !

Dans la fonction Swap, les variables a et b sont des copies de x et y. On ne modifie que ces copies, les originaux restent intacts.

Exemple avec ref — les variables sont échangées


// On échange les valeurs des variables avec ref
void Swap(ref int a, ref int b)
{
    int temp = a;
    a = b;
    b = temp;
}

int x = 10;
int y = 20;
Swap(ref x, ref y); // On passe les références des variables
Console.WriteLine($"{x}, {y}"); // → 20, 10 — tout a bien été échangé
        

ref permet de passer la référence de la variable, pas juste sa valeur.
Du coup, la fonction Swap bosse directement avec x et y, et modifie leur contenu.

Quand utiliser ref ?

  • Quand tu veux modifier la variable passée (genre l'incrémenter, la remplacer).
  • Pas besoin de retourner une nouvelle valeur (comme avec return), tu veux juste modifier l'argument direct.
  • Évite de l'utiliser pour "balancer" plein de valeurs différentes — pour ça, y'a un autre modificateur.

3. Modificateur out : On passe vers l'extérieur

Maintenant, imagine : tu vas chez ton pote, mais t'as une tasse vide, et tu lui demandes : "Remplis la tasse — ce que tu veux, café ou thé !" Après ça, ton pote est obligé de la remplir, sinon le compilateur va râler.

out est fait pour que la méthode puisse retourner plusieurs valeurs différentes, sans passer par la valeur de retour. Ces paramètres doivent absolument être initialisés dans la méthode.


void GetCoordinates(out int x, out int y)
{
    x = 5;
    y = 10; // Sans ça - erreur !
}
        
Méthode avec des paramètres out
  • Avant l'appel : la variable peut ne pas être initialisée, tu peux même écrire juste out int x dans l'appel.
  • Dans la méthode : il faut absolument affecter une valeur avant de sortir, sinon le compilateur fait la grève.
  • Après l'appel : la variable contient la nouvelle valeur.

Exemple : On retourne deux valeurs d'une méthode

void ParseNameAndAge(string input, out string name, out int age)
{
    string[] parts = input.Split(',');	// on transforme la chaîne en tableau de chaînes - on découpe par ','
    name = parts[0];
    age = int.Parse(parts[1]);
}

string userInput = "Ivan,25";
ParseNameAndAge(userInput, out string userName, out int userAge);
Console.WriteLine($"{userName} — {userAge} ans");

Quand utiliser out ?

  • Quand tu veux retourner plusieurs valeurs d'une méthode (genre découper une chaîne, comme ci-dessus).
  • Quand le type de valeur de retour n'est pas connu à l'avance (genre essayer de convertir une chaîne en nombre).

Exemples dans .NET : La méthode int.TryParse(string, out int) — un classique !

string input = "123";
if (int.TryParse(input, out int parsedNumber))
{
    Console.WriteLine($"Converti : {parsedNumber}");
}
else
{
    Console.WriteLine("Erreur de conversion !");
}

La méthode int.TryParse retourne true si elle a réussi à convertir la chaîne en nombre, et false sinon. La valeur numérique elle-même est retournée via out.

Erreurs classiques et situations marrantes avec ref et out

  • T'as oublié d'initialiser la variable pour ref — le compilateur râle.
  • T'as pas affecté de valeur pour out — le compilateur est encore plus vénère.
  • T'as oublié de mettre le modificateur à l'appel : t'as écrit DoSomething(x) au lieu de DoSomething(ref x).
  • Utiliser ref ou out avec des constantes ou des littéraux, c'est interdit ! Il faut que ce soit des variables. Elles seules ont une adresse mémoire sur laquelle on peut faire une référence.

4. Modificateur in : Lecture seule, et seulement par référence

Parfois, tu dois passer un objet gros et complexe à une méthode. D'habitude, un objet comme ça est déjà passé par référence, mais il peut être modifié par la fonction qui a un accès complet — vu qu'on lui a filé la référence.

Théoriquement, tu pourrais faire une copie complète de ton objet et la passer. Comme ça, personne ne touche à l'original. Mais si l'objet est énorme, tu vas copier plein de données pour rien. Ce serait mieux de passer l'objet à la fonction et demander au compilateur de vérifier que personne ne le modifie.

in — c'est un modificateur récent, qui permet de passer des structures par référence, mais en lecture seule. C'est comme "exposer une épée précieuse sous une vitrine" : tu peux regarder, mais pas toucher.


void PrintPoint(in Point pt)
{
    pt.X = 5; // Erreur ! Lecture seule.
    Console.WriteLine($"Point : {pt.X}, {pt.Y}");  //Ça, c'est ok
}
        
Méthode avec un paramètre in (lecture seule)
  • Avant l'appel : la variable doit être initialisée.
  • Dans la méthode : tu peux seulement lire, pas modifier.
  • Économie de mémoire : la structure n'est pas copiée, elle est passée par référence.

C'est utile, par exemple, pour des tableaux de grosses structures, pour éviter des copies inutiles. Mais avec les classes (types référence), in n'apporte pas grand-chose.

Exemple : On passe une grosse structure par référence, sans la copier

struct BigData
{
    public int A, B, C, D, E;
}

void PrintBigData(in BigData data)
{
    data.A = 10; // interdit - lecture seule !
    Console.WriteLine(data.A + data.B + data.C + data.D + data.E);
}

BigData myData = new BigData { A = 10, B = 20, C = 30, D = 40, E = 50 };
PrintBigData(in myData);

5. Questions qu'on se pose souvent :

Est-ce qu'on peut utiliser ref/out/in avec des tableaux et des types référence ?
Oui, carrément ! Mais rappelle-toi : les tableaux sont déjà des types référence. Si tu passes un tableau avec ref, tu peux changer la référence elle-même. Le plus souvent, c'est utile pour les structures.

C'est quoi la différence entre ref et out, vu que je peux récupérer une valeur dans les deux cas ?
Avec ref, la variable doit être initialisée avant de l'utiliser. Avec out, pas besoin, mais dans la méthode elle DOIT être affectée au moins une fois.

Et si j'essaie d'utiliser un littéral (genre le nombre 5) avec ref/out/in ?
Le compilateur va direct sortir une erreur. Uniquement des variables !

Combien de paramètres je peux mettre en ref/out/in ?
Autant que tu veux, pas de limite ! Mais abuse pas pour la lisibilité du code : si t'en as plus de deux ou trois, pense à retourner un tuple, une structure ou une classe.

2
Mission
C# SELF, niveau 12, leçon 4
Bloqué
Utilisation du modificateur ref
Utilisation du modificateur ref
2
Mission
C# SELF, niveau 12, leçon 4
Bloqué
Utilisation du modificateur out
Utilisation du modificateur out
1
Étude/Quiz
Classes et objets, niveau 12, leçon 4
Indisponible
Classes et objets
Introduction à l'héritage
Commentaires
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION