Menu

Méthodes en C# : paramètres, valeurs de retour, params, surcharge et Main

Comment déclarer et appeler des méthodes en C# : types de retour et void, paramètres, méthodes à corps d'expression, renvoyer plusieurs valeurs avec un tuple, surcharge, tableaux params, méthodes statiques ou d'instance, la méthode Main, la récursivité et les fonctions locales.

Cette page contient des éditeurs exécutables - modifiez, exécutez et voyez la sortie instantanément.

Une méthode est un bloc de code nommé qui reçoit des entrées (les paramètres), fait son travail et peut rendre un résultat (la valeur de retour). En C#, chaque méthode vit dans un type ; il n'existe pas de fonctions indépendantes.

Sortie :

Headphones   48.00
Cable        11.40

Anatomie d'une méthode

public static decimal PriceWithTax(decimal net, decimal taxRate)
{
    return net * (1 + taxRate);
}
  • Modificateur d'accès (public, private, ...) : qui peut l'appeler. S'il est omis, une méthode est private à son type.
  • static : la méthode appartient au type, pas à un objet. Plus de détails ci-dessous.
  • Type de retour : le type de la valeur renvoyée, ou void s'il n'y en a pas.
  • Nom : en PascalCase par convention, en général un verbe (Calculate, SendEmail, TryParse).
  • Liste de paramètres : zéro ou plusieurs paires type name. Chaque paramètre est une variable locale initialisée à partir de l'argument de l'appelant.
  • Corps : les instructions entre les accolades.

Le nom et les types des paramètres (avec les éventuels modificateurs ref, out ou in) forment la signature de la méthode. Le type de retour n'en fait pas partie, ce qui compte pour la surcharge.

Valeurs de retour et void

return termine immédiatement la méthode et rend une valeur. Une méthode dotée d'un type de retour doit renvoyer une valeur de ce type sur chaque chemin qui la traverse :

static string Grade(int score)
{
    if (score >= 50)
        return "pass";
}   // error CS0161: 'Program.Grade(int)': not all code paths return a value

Le compilateur vérifie chaque branche. Ajoutez le return "fail"; manquant, ou un throw si atteindre ce point est un bug.

Une méthode void ne renvoie rien. Elle peut quand même utiliser un return; seul pour sortir plus tôt :

Sortie :

ana@mail.com: newsletter sent
ben@mail.com: not subscribed, skipped
False
True

Méthodes à corps d'expression

Quand le corps d'une méthode est une seule expression, => remplace les accolades et le return :

static decimal Discount(decimal price) => price * 0.1m;
static bool IsAdult(int age) => age >= 18;
static void Log(string message) => Console.WriteLine($"[log] {message}");

C'est la même méthode, écrite plus court. Cela fonctionne aussi pour les méthodes void, tant que le corps est une seule expression (un appel, une affectation).

Les paramètres sont des copies

Les arguments sont passés par valeur par défaut : le paramètre reçoit une copie de l'argument. Affecter le paramètre dans la méthode n'affecte pas la variable de l'appelant :

Sortie :

inside: 42
after:  21
scores: 70, 85, 100

La List a changé parce que, pour un type référence, la valeur copiée est la référence : la méthode et l'appelant pointent vers le même objet liste. Réaffecter scores = new List<int>() dans la méthode n'affecterait pas l'appelant. Pour permettre à une méthode d'affecter la variable de l'appelant, utilisez ref ou out ; pour donner des valeurs par défaut aux paramètres et les appeler par leur nom, utilisez les paramètres optionnels et les arguments nommés.

Renvoyer plusieurs valeurs avec un tuple

Depuis C# 7.0, une méthode peut renvoyer un tuple aux éléments nommés, et l'appelant peut le déconstruire en variables séparées :

Sortie :

min 15, max 27, avg 21.0
range 12

_ ignore l'élément dont vous n'avez pas besoin. Pour des résultats utilisés à de nombreux endroits, une petite classe ou un record avec des propriétés nommées documente mieux la forme qu'un tuple.

La surcharge

Plusieurs méthodes peuvent partager un nom si leurs listes de paramètres diffèrent par le nombre, les types ou l'ordre des types. Le compilateur choisit la meilleure correspondance pour chaque appel :

Sortie :

12.57
13.50
25

Area(5) choisit la version int car c'est une correspondance exacte ; Area(2.0) choisit la version double. Des méthodes ne peuvent pas différer uniquement par leur type de retour : deux méthodes Area(int) qui renvoient int et double donnent l'erreur CS0111, Type 'Program' already defines a member called 'Area' with the same parameter types, car un appel comme Area(5) ne pourrait pas les distinguer.

Un appel qu'aucune surcharge n'accepte échoue aussi à la compilation : Area(1, 2, 3) donne CS1501, No overload for method 'Area' takes 3 arguments, et Area("big") donne CS1503, Argument 1: cannot convert from 'string' to 'double'.

params : un nombre variable d'arguments

Un paramètre tableau params accepte n'importe quel nombre d'arguments, y compris aucun. Le compilateur construit le tableau pour vous :

Sortie :

empty cart: 0 item(s), 0
one item: 1 item(s), 9.99
three items: 3 item(s), 19.75
from array: 2 item(s), 50

Règles : params doit être le dernier paramètre (sinon CS0231), une méthode en a au plus un, et passer un tableau existant transmet ce tableau tel quel. Console.WriteLine("{0} and {1}", a, b) et string.Format sont des méthodes params object[]. C# 13 a étendu params à d'autres types de collection comme List<T> et ReadOnlySpan<T> ; auparavant, seuls les tableaux étaient autorisés.

Méthodes statiques et méthodes d'instance

Une méthode static appartient au type et s'appelle sur le nom du type : Math.Max(3, 7), Program.Total(...). Une méthode d'instance appartient à un objet et peut utiliser les champs de cet objet :

Sortie :

12

Appeler une méthode d'instance depuis une méthode statique sans objet est l'erreur de débutant la plus courante en C# :

class Program
{
    void Greet() => Console.WriteLine("hi");

    static void Main()
    {
        Greet();
        // error CS0120: An object reference is required for the non-static field, method, or property 'Program.Greet()'
    }
}

Marquez Greet comme static, ou créez un objet et appelez la méthode dessus : new Program().Greet();. La page sur static détaille les membres statiques et les classes statiques.

La méthode Main

Main est l'endroit où démarre un programme. Elle doit être static, et ces signatures sont valides :

static void Main() { }
static void Main(string[] args) { }            // command-line arguments
static int Main(string[] args) { return 0; }   // exit code for the shell
static async Task Main() { }                    // C# 7.1 and later

La forme async Task Main permet au point d'entrée d'utiliser directement await (voir async et await). Depuis C# 9, un fichier peut à la place contenir des instructions de niveau supérieur : du code sans classe ni Main, comme dans un nouveau projet dotnet new console. Le compilateur génère la classe et la méthode Main autour, c'est donc la même chose écrite plus court ; args reste disponible.

La récursivité

Une méthode peut s'appeler elle-même. Chaque appel reçoit ses propres paramètres et variables locales, et un cas de base doit arrêter la chaîne :

Sortie :

120
2432902008176640000
35

Sans cas de base, ou avec une entrée trop profonde, chaque appel ajoute un cadre de pile jusqu'à ce que le programme meure avec une StackOverflowException. Cette exception ne peut pas être interceptée ; pour une entrée de profondeur inconnue, réécrivez donc la récursivité sous forme de boucle.

Les fonctions locales

C# 7.0 a introduit les fonctions locales : des méthodes déclarées dans une autre méthode et visibles seulement là. Elles peuvent utiliser les variables de la méthode englobante :

// C# 7.0 and later
static int CountValid(string[] codes)
{
    int count = 0;
    foreach (string code in codes)
    {
        if (IsValid(code)) count++;
    }
    return count;

    bool IsValid(string c) => c.Length == 6 && char.IsLetter(c[0]);
}

Elles gardent une fonction auxiliaire à côté de son unique appelant sans l'exposer au reste de la classe. Depuis C# 8, on peut les marquer static pour interdire la capture de variables externes. Là où une fonction locale n'est pas disponible, une méthode privée statique de la même classe fait le même travail, comme dans les autres exemples de cette page.

Questions fréquentes

Quelle est la différence entre une méthode et une fonction en C# ?

En C#, chaque fonction est déclarée dans une classe, une struct ou un record, et s'appelle une méthode. Il n'existe pas de fonctions indépendantes. Même les instructions de niveau supérieur (C# 9) et les fonctions locales (C# 7) sont compilées en méthodes d'un type généré ou englobant. Le mot « fonction » s'emploie de façon informelle, et pour les lambdas et les délégués.

À quoi sert params en C# ?

params permet à une méthode de recevoir un nombre variable d'arguments d'un même type : static int Sum(params int[] numbers) peut s'appeler Sum(), Sum(4), Sum(4, 5, 6) ou Sum(existingArray). Le compilateur regroupe les arguments dans un tableau. Le paramètre params doit être le dernier, et une méthode ne peut en avoir qu'un.

Qu'est-ce que la méthode Main en C# ?

Main est le point d'entrée du programme : la méthode que le runtime appelle en premier. Elle doit être static, peut renvoyer void ou int (le code de sortie) et peut prendre string[] args pour les arguments de la ligne de commande. Depuis C# 7.1, elle peut aussi être async Task Main, et depuis C# 9 les instructions de niveau supérieur laissent le compilateur la générer pour vous.

Comment renvoyer plusieurs valeurs depuis une méthode C# ?

Renvoyez un tuple : static (int Min, int Max) Range(int[] values) et return (min, max);. L'appelant peut lire result.Min ou déconstruire avec var (lo, hi) = Range(values);. Pour des valeurs qui voyagent ensemble dans tout votre code, une petite classe ou un record est plus clair ; les paramètres out sont l'alternative plus ancienne.

Pourquoi obtient-on « An object reference is required for the non-static field, method, or property » ?

Une méthode static comme Main a appelé directement une méthode d'instance. Les méthodes statiques appartiennent au type et n'ont aucun objet sur lequel l'appeler. Marquez la méthode appelée comme static, ou créez d'abord un objet : var app = new Program(); app.Greet();.

Que signifie « not all code paths return a value » ?

Erreur CS0161 : une méthode dotée d'un type de retour a au moins un chemin qui atteint l'accolade fermante sans return. En général, un if renvoie une valeur mais il n'y a ni else ni return final après lui. Ajoutez un return (ou un throw) à la fin de la méthode.

Coddy programming languages illustration

Apprendre à coder avec Coddy

COMMENCER