Méthodes (Guide de programmation C#)

Une méthode est un bloc de code qui contient une série d'instructions. Un programme provoque l'exécution des instructions en appelant la méthode et en spécifiant les éventuels arguments de méthode requis. En C#, chaque instruction exécutée est effectuée dans le contexte d'une méthode.

La méthode Main est le point d’entrée de chaque application C# et elle est appelée par le Common Language Runtime (CLR) au démarrage du programme. Dans une application qui utilise des instructions de niveau supérieur, la méthode Main est générée par le compilateur et contient toutes les instructions de niveau supérieur.

Notes

Cet article traite les méthodes nommées. Pour plus d’informations sur les fonctions anonymes, consultez Expressions lambda.

Signatures de méthode

Les méthodes sont déclarées dans une classe, struct ou interface en spécifiant le niveau d'accès comme public ou private, les modificateurs facultatifs comme abstract ou sealed, la valeur de retour, le nom de la méthode et les éventuels paramètres de méthode. Ces parties forment ensemble la signature de la méthode.

Important

Un type de retour d'une méthode ne fait pas partie de la signature de la méthode à des fins de surcharge de méthode. Toutefois, il fait partie de la signature de la méthode lors de la détermination de la compatibilité entre un délégué et la méthode vers laquelle il pointe.

Les paramètres de méthode sont placés entre parenthèses et séparés par des virgules. Des parenthèses vides indiquent que la méthode ne requiert aucun paramètre. Cette classe contient quatre méthodes :

abstract class Motorcycle
{
    // Anyone can call this.
    public void StartEngine() {/* Method statements here */ }

    // Only derived classes can call this.
    protected void AddGas(int gallons) { /* Method statements here */ }

    // Derived classes can override the base class implementation.
    public virtual int Drive(int miles, int speed) { /* Method statements here */ return 1; }

    // Derived classes must implement this.
    public abstract double GetTopSpeed();
}

Accès aux méthodes

L'appel d'une méthode sur un objet revient à accéder à un champ. Après le nom de l'objet, ajoutez un point, le nom de la méthode et les parenthèses. Les arguments sont répertoriés entre les parenthèses et séparés par des virgules. Les méthodes de la classe Motorcycle peuvent donc être appelées comme dans l'exemple suivant :

class TestMotorcycle : Motorcycle
{
    public override double GetTopSpeed()
    {
        return 108.4;
    }

    static void Main()
    {
        TestMotorcycle moto = new TestMotorcycle();

        moto.StartEngine();
        moto.AddGas(15);
        moto.Drive(5, 20);
        double speed = moto.GetTopSpeed();
        Console.WriteLine("My top speed is {0}", speed);
    }
}

Paramètres de méthode et arguments

La définition de la méthode spécifie les noms et types des paramètres requis. Quand le code appelant appelle la méthode, il fournit des valeurs concrètes appelées arguments pour chaque paramètre. Les arguments doivent être compatibles avec le type de paramètre, mais le nom de l'argument (le cas échéant) utilisé dans le code appelant ne doit pas nécessairement être le même que celui du paramètre défini dans la méthode. Par exemple :

public void Caller()
{
    int numA = 4;
    // Call with an int variable.
    int productA = Square(numA);

    int numB = 32;
    // Call with another int variable.
    int productB = Square(numB);

    // Call with an integer literal.
    int productC = Square(12);

    // Call with an expression that evaluates to int.
    productC = Square(productA * 3);
}

int Square(int i)
{
    // Store input argument in a local variable.
    int input = i;
    return input * input;
}

Passer par référence et passer par valeur

Par défaut, lorsqu’une instance d’un type valeur est passée à une méthode, sa copie est passée au lieu de l’instance elle-même. Ainsi, les modifications apportées à l'argument n'ont aucun effet sur l’instance d'origine dans la méthode d'appel. Pour passer une instance de type valeur par référence, utilisez le mot clé ref. Pour plus d’informations, consultez Passage de paramètres de type valeur .

Quand un objet d'un type référence est passé à une méthode, une référence à l'objet est passée. Autrement dit, la méthode ne reçoit pas l'objet lui-même mais un argument qui indique l'emplacement de l'objet. Si vous modifiez un membre de l'objet à l'aide de cette référence, la modification est répercutée dans l'argument de la méthode d'appel, même si vous passez l'objet par valeur.

Vous créez un type référence à l'aide du mot clé class, comme le montre l'exemple suivant :

public class SampleRefType
{
    public int value;
}

Maintenant, si vous passez un objet basé sur ce type à une méthode, une référence à l'objet est passée. L'exemple suivant passe un objet de type SampleRefType à la méthode ModifyObject :

public static void TestRefType()
{
    SampleRefType rt = new SampleRefType();
    rt.value = 44;
    ModifyObject(rt);
    Console.WriteLine(rt.value);
}

static void ModifyObject(SampleRefType obj)
{
    obj.value = 33;
}

L'exemple produit essentiellement la même chose que l'exemple précédent, dans la mesure où il passe un argument par valeur à une méthode. Mais, puisqu'un type référence est utilisé, le résultat est différent. La modification apportée dans ModifyObject au champ value du paramètre, obj, modifie également le champ value de l'argument, rt, dans la méthode TestRefType . La méthode TestRefType affiche 33 en tant que sortie.

Pour plus d’informations sur le passage de types référence par référence et par valeur, consultez Passage de paramètres de type référence et Types référence.

Valeurs de retour

Les méthodes peuvent retourner une valeur à l'appelant. Si le type de retour (le type qui figure avant le nom de la méthode) n’est pas void, la méthode peut retourner la valeur en utilisant return l’instruction. Une instruction avec le mot clé return suivi d'une valeur qui correspond au type de retour retourne cette valeur à l'appelant de la méthode.

La valeur peut être retournée à l’appelant par valeur ou par référence. Les valeurs sont retournées à l’appelant par référence si le mot clé ref est utilisé dans la signature de méthode et s’il suit chaque mot clé return. Par exemple, la signature de méthode suivante et l’instruction de retour indiquent que la méthode retourne une variable nommée estDistance par référence à l’appelant.

public ref double GetEstimatedDistance()
{
    return ref estDistance;
}

Le mot clé return arrête également l'exécution de la méthode. Si le type de retour est void, une instruction return sans valeur est quand même utile pour arrêter l'exécution de la méthode. Sans le mot clé return , la méthode arrête de s'exécuter quand elle atteint la fin du bloc de code. Les méthodes dotées d'un type de retour non void doivent utiliser le mot clé return pour retourner une valeur. Par exemple, ces deux méthodes utilisent le mot clé return pour retourner des entiers :

class SimpleMath
{
    public int AddTwoNumbers(int number1, int number2)
    {
        return number1 + number2;
    }

    public int SquareANumber(int number)
    {
        return number * number;
    }
}

Pour utiliser une valeur retournée à partir d'une méthode, la méthode d'appel peut utiliser l'appel de méthode proprement dit partout où une valeur du même type peut suffire. Vous pouvez également affecter la valeur de retour à une variable. Par exemple, les deux exemples de code suivants remplissent le même objectif :

int result = obj.AddTwoNumbers(1, 2);
result = obj.SquareANumber(result);
// The result is 9.
Console.WriteLine(result);
result = obj.SquareANumber(obj.AddTwoNumbers(1, 2));
// The result is 9.
Console.WriteLine(result);

L'utilisation d'une variable locale, dans cet exemple, result, pour stocker une valeur est facultative. Elle peut favoriser la lisibilité du code ou s'avérer nécessaire si vous avez besoin de stocker la valeur d'origine de l'argument pour la portée entière de la méthode.

Pour utiliser une valeur retournée par référence à partir d’une méthode, vous devez déclarer une variable ref local si vous avez l’intention de modifier sa valeur. Par exemple, si la méthode Planet.GetEstimatedDistance retourne une valeur Double par référence, vous pouvez la définir en tant que variable ref local avec du code semblable à celui-ci :

ref double distance = ref Planet.GetEstimatedDistance();

Le retour d’un tableau multidimensionnel à partir d’une méthode, M, qui modifie le contenu du tableau n’est pas nécessaire si la fonction appelante a passé le tableau à M. Vous pouvez retourner le tableau obtenu à partir de M pour bénéficier d’un style approprié ou d’un flux fonctionnel de valeurs, mais cela n’est pas nécessaire, car C# passe tous les types de référence par valeur, et la valeur d’une référence de tableau est le pointeur qui désigne le tableau. Dans la méthode M, les modifications apportées au contenu du tableau sont observables par tout code ayant une référence au tableau, comme dans l’exemple suivant :

static void Main(string[] args)
{
    int[,] matrix = new int[2, 2];
    FillMatrix(matrix);
    // matrix is now full of -1
}

public static void FillMatrix(int[,] matrix)
{
    for (int i = 0; i < matrix.GetLength(0); i++)
    {
        for (int j = 0; j < matrix.GetLength(1); j++)
        {
            matrix[i, j] = -1;
        }
    }
}

Méthodes Async

La fonctionnalité async vous permet d'appeler des méthodes asynchrones sans utiliser de rappels explicites ni fractionner manuellement votre code entre plusieurs méthodes ou expressions lambda.

Si vous marquez une méthode avec le modificateur async, vous pouvez utiliser l’opérateur await dans la méthode. Quand le contrôle atteint une expression await dans la méthode async, il retourne à l'appelant, et la progression dans la méthode est interrompue jusqu'à ce que la tâche attendue se termine. Quand la tâche est terminée, l'exécution peut reprendre dans la méthode.

Notes

Une méthode asynchrone retourne à l'appelant quand elle rencontre le premier objet attendu qui n'est pas encore terminé ou quand elle atteint la fin de la méthode asynchrone, selon la première éventualité.

Une méthode asynchrone a généralement un type de retour Task<TResult>, Task, IAsyncEnumerable<T> ou void . Le type de retour void est essentiellement utilisé pour définir les gestionnaires d’événements, où un type de retour void est obligatoire. Une méthode async qui retourne void ne peut pas être attendue, et l’appelant d’une méthode retournant void ne peut intercepter aucune exception levée par la méthode. Une méthode asynchrone peut avoir n’importe quel type de retour de type tâche.

Dans l'exemple suivant, DelayAsync est une méthode async dont le type de retour est Task<TResult>. DelayAsync a une instruction return qui retourne un entier. Ainsi, la déclaration de méthode de DelayAsync doit avoir un type de retour de Task<int>. Étant donné que le type de retour est Task<int>, l'évaluation de l'expression await dans DoSomethingAsync produit un entier, comme le montre l'instruction suivante : int result = await delayTask.

La méthode Main est un exemple de méthode asynchrone dont le type de retour est Task. Elle accède à la méthode DoSomethingAsync et étant donné qu’elle est exprimée avec une seule ligne, elle peut omettre les mots clés async et await. Étant donné que DoSomethingAsync est une méthode async, la tâche pour l'appel à DoSomethingAsync doit être attendue, comme le montre l'instruction suivante : await DoSomethingAsync();.

class Program
{
    static Task Main() => DoSomethingAsync();

    static async Task DoSomethingAsync()
    {
        Task<int> delayTask = DelayAsync();
        int result = await delayTask;

        // The previous two statements may be combined into
        // the following statement.
        //int result = await DelayAsync();

        Console.WriteLine($"Result: {result}");
    }

    static async Task<int> DelayAsync()
    {
        await Task.Delay(100);
        return 5;
    }
}
// Example output:
//   Result: 5

Une méthode async ne peut pas déclarer de paramètres ref ou out , mais elle peut appeler des méthodes qui comportent ces paramètres.

Pour plus d’informations sur les méthodes asynchrones, consultez Programmation asynchrone avec asynchrone et await et Types de retour asynchrones.

Définitions de corps d’expression

Il est courant d'avoir des définitions de méthode qui retournent tout simplement le résultat d'une expression immédiatement, ou qui ont une seule instruction en tant que corps de la méthode. Il existe un raccourci de syntaxe pour définir de telles méthodes en utilisant =>:

public Point Move(int dx, int dy) => new Point(x + dx, y + dy);
public void Print() => Console.WriteLine(First + " " + Last);
// Works with operators, properties, and indexers too.
public static Complex operator +(Complex a, Complex b) => a.Add(b);
public string Name => First + " " + Last;
public Customer this[long id] => store.LookupCustomer(id);

Si la méthode retourne void ou est une méthode async, alors le corps de la méthode doit être une expression d'instruction (même chose avec les expressions lambda). En ce qui concerne les propriétés et indexeurs, ils doivent être en lecture seule et vous n'utilisez pas le mot clé d'accesseur get.

Iterators

Un itérateur exécute une itération personnalisée sur une collection, comme une liste ou un tableau. Un itérateur utilise l'instruction yield return pour retourner chaque élément un par un. Quand une instruction yield return est atteinte, l’emplacement actuel dans le code est mémorisé. L'exécution redémarre à partir de cet emplacement au prochain appel de l'itérateur.

Vous appelez un itérateur depuis le code client en utilisant une instruction foreach.

Le type de retour d'un itérateur peut être IEnumerable, IEnumerable<T>, IAsyncEnumerable<T>, IEnumerator ou IEnumerator<T>.

Pour plus d'informations, consultez Itérateurs.

spécification du langage C#

Pour plus d'informations, voir la spécification du langage C#. La spécification du langage est la source de référence pour la syntaxe C# et son utilisation.

Voir aussi