Passage par référence d’un objet

J’ai eu une question aujourd’hui :

“Si je passe un objet à une méthode qui ne retourne rien mais qui modifie l’objet en paramètre, est-ce que je peux enlever le ref dans la signature de ma méthode ?” 

Ma première pensée a été de répondre oui, ce qui en fait n’est pas tout à fait vrai.

Définissons une classe Personne comme suit :

    public class Personne
    {
        public string Nom { get; set; }
    }

Bon, on peut guère faire plus simple! Maintenant je vais définir deux méthodes, l’une avec un passage de paramètre par référence et l’autre sans. Ces deux méthodes font exactement la même chose.

        static void MethodeParReference(ref Personne personne)
        {
            personne.Nom = "George";
        }

        static void MethodeSansReference(Personne personne)
        {
            personne.Nom = "George";
        }

Pour tester mes deux méthodes je complète la méthode main de mon application console comme suit :

static void Main(string[] args)
        {
            Personne personne1 = new Personne() { Nom = "Jean" };
            Personne personne2 = new Personne() { Nom = "Jean" };

            MethodeParReference(ref personne1);
            Console.WriteLine(personne1.Nom);

            MethodeSansReference(personne2);
            Console.WriteLine(personne2.Nom);

            Console.ReadLine();
        }

Le résultat est bien le même quelque soit la méthode appelée.

Appliquons désormais une modification qui peut paraître anodine à nos deux méthodes

        static void MethodeParReference(ref Personne personne)
        {
            personne = new Personne();
            personne.Nom = "George";
        }

        static void MethodeSansReference(Personne personne)
        {
            personne = new Personne();
            personne.Nom = "George";
        }

En relançant notre méthode de test on se rend compte que cette fois-ci le résultat est totalement différent. La méthode avec passage par référence modifie bien l’objet passé en paramètre. En effet dans ce cas on passe la variable elle-même et non la valeur de la variable. Ceci fait que l’appel au constructeur de personne modifie bel et bien la variable elle-même, on retrouve ainsi bien sa nouvelle valeur dans la méthode Main.

On a pour habitude de dire que les objets sont par défaut passés par référence, en vérité par défaut on passe par valeur la référence à l’objet , ci cette valeur est modifiée (cas d’un new) alors on la perd dans la méthode appelante. Tant qu’on ne modifie que les propriétés de l’objet sa référence ne change pas, d’où le premier exemple qui fonctionne très bien.