Bien comprendre les mots-clés « ref » et « out » en C#

Explication d'une manière synthétique sur le fonctionnement des mots clés ref et out, exclusifs au langage C#.

Avant d'aller plus loin dans cet article, il est nécessaire de bien comprendre la différence entre les types valeur et les types référence. Cette différence fera l'objet d'un article mais vous pouvez consulter cette différence ici : MSDN - Types valeur et référence

ref

Pour bien comprendre ref, nous allons directement prendre un morceau de code qui utilise ce mot clé :

using System;
					
public class Program
{
	public static void Main()
	{
		int a = 10;
		Add10(ref a);
		Console.WriteLine(a); // En sortie : 20
	}
	
	public static void Add10(ref int a)
	{
		a += 10;
	}
}

Comme vous pouvez le constater, le mot clé doit-être utilisé comme argument aussi bien lors de la déclaration d'une méthode que lors de son appel. ref va donc nous permettre de passer la référence de la variable dans le but de modifier directement sa valeur sans passé par la création d'une copie. En effet, lors du passage d'un argument de type valeur, c'est bien une copie que l'on manipule et non directement sa valeur, contrairement aux types références. Ainsi notre bout de code va retourner 20. L'absence du mot-clé nous aurait retourné 10.

out

Le mot-clé out permet pour une méthode, de pouvoir retourner plusieurs résultats en plus de sa valeur de retour. En effet, grâce à l'utilisation de ce mot-clé, vous allez pouvoir déclarer des variables sans les initialiser et les affecter lors de leur passage dans le corps d'une méthode à travers ses paramètres. Attention la méthode contenant un paramètre out doit nécessairement affecter la variable associée.

using System;
					
public class Program
{
	public static void Main()
	{
		int a;
		Set10(out a);
		Console.WriteLine(a); // En sortie : 10
	}
	
	public static void Set10(out int a)
	{
		a = 10;
	}
}

Ainsi, dans cet exemple très simple, nous observons un type valeur (a) qui n'a pas besoin d'être initialisé grâce à l'utilisation du mot clé out.

Un exemple concret d'utilisation de ce mot clé est la méthode TryParse de la class Int32. Cette méthode permet de retourner deux choses :

  • De vérifier s'il est possible d'effectuer une conversion d'une string vers un int (le paramètre de retour de la fonction retourne cette possibilité ou non par un type booléen)
  • De pouvoir, dans le cas possible d'une conversion, d'affecter cette string dans un int passé en paramètre avec le mot-clé out.
using System;

using System;

public class StringParsing
{
   public static void Main()
   {
      int number;
      bool result = int.TryParse("1234", out number);
      Console.WriteLine("number : {0} , conversion en int possible ? {1}", number, result);
	   
      int notANumber;
      result = int.TryParse("bonsoir", out notANumber);
      Console.WriteLine("notANumber : {0}, bonsoir, conversion en int possible ? {1}.", notANumber, result);

      //En sortie :
      //number : 1234 , conversion en int possible ? True
      //notANumber : 0, bonsoir, conversion en int possible ? False.
   }
}

A noter que pour le deuxième test, notANumber prend la valeur par défaut d'un int si la conversion est impossible : c'est à dire zero.

Nouveauté avec C# 7 concernant out

Depuis la version 7 de C#, il est possible de déclarer directement "inline" la variable out dans les arguments d'une méthode !
Avant nous devions déclarer une variable seule comme sur le code ci-dessous :

var result;
int.TryParse(input, out result)

Et désormais, nous pourrons écrire ceci :

int.TryParse(input, out var result)