En programmation C#, la communication entre les méthodes repose sur l'échange de données via des paramètres. Avant d'explorer les différentes méthodes de transfert, il est essentiel de distinguer deux concepts fondamentaux :
- Paramètres formels : Ce sont les variables déclarées dans la signature d'une méthode. Ils servent de réceptacles pour les données entrantes.
- Arguments (ou paramètres réels) : Ce sont les valeurs concrètes transmises à la méthode lors de son appel.
Le langage C# propose trois mécanismes principaux pour transmettre ces données : le passage par valeur, le passage par référence (ref) et le passsage par sortie (out).
1. Le passage par valeur (Par défaut)
Il s'agit du comportement standard en C#. Lorsqu'un argument est transmis par valeur, le système crée une copie locale de la donnée. La méthode travaille sur cette copie, ce qui garantit que la variable d'origine reste inchangée dans le code appelant, car elles occupent des emplacements distincts en mémoire.
using System;
namespace ProgrammationCS
{
class DemoValeur
{
static void Main()
{
int score = 50;
Console.WriteLine($"Avant appel : {score}");
ModifierScore(score);
Console.WriteLine($"Après appel : {score}");
}
static void ModifierScore(int points)
{
points += 100;
Console.WriteLine($"Dans la méthode : {points}");
}
}
}
Dans cet exemple, la modification de points n'affecte pas score. Le résultat affiche 50 après l'exécution de la méthode.
2. Le passage par référence (Mot-clé ref)
Le passage par référence permet à une méthode d'accéder directement à l'emplacement mémoire de la variable d'origine. Contrairement au passage par valeur, aucune copie n'est effectuée. Toute modification apportée au paramètre formel impacte directement l'argument initial. Pour utiliser ce mode, le mot-clé ref doit être présent à la fois dans la définition de la méthode et lors de l'appel.
Note : La variable transmise via ref doit impérativement être initialisée avant d'être passée à la méthode.
using System;
namespace ProgrammationCS
{
class DemoRef
{
static void Main()
{
int niveau = 1;
Console.WriteLine($"Niveau initial : {niveau}");
MonterDeNiveau(ref niveau);
Console.WriteLine($"Niveau final : {niveau}");
}
static void MonterDeNiveau(ref int lv)
{
lv++;
Console.WriteLine($"Progression enregistrée : {lv}");
}
}
}
3. Le passage par sortie (Mot-clé out)
Le mot-clé out est conceptuellement proche de ref car il permet de modifier la varible d'origine. Cependant, il est spécifiquement conçu pour retourner plusieurs valeurs depuis une méthode. À la différence de ref, il n'est pas nécessaire d'initialiser la variable avant l'appel. En revanche, la méthode réceptrice a l'obligation d'assigner une valeur au paramètre out avant de se terminer.
using System;
namespace ProgrammationCS
{
class DemoOut
{
static void Main()
{
double rayon = 5.5;
double aire, perimetre;
CalculerCercle(rayon, out aire, out perimetre);
Console.WriteLine($"Rayon : {rayon}");
Console.WriteLine($"Aire calculée : {aire:F2}");
Console.WriteLine($"Périmètre calculé : {perimetre:F2}");
}
static void CalculerCercle(double r, out double a, out double p)
{
a = Math.PI * Math.Pow(r, 2);
p = 2 * Math.PI * r;
}
}
}
Le passage par sortie est également très utilisé dans les méthodes de parsing (comme int.TryParse) pour renvoyer à la fois un booléen de succès et la valeur convertie.