Accueil logo MakeYourGame gachetteG gachetteD paddleG paddleH paddleD paddleB buttonG buttonH buttonD buttonB

C# : les fonctions

Langage C#

Dans plusieurs chapitres concernant les bases du C#, nous avons vu la déclaration de variable, les branchements conditionnels et les boucles. Dans ce chapitre, nous verrons un dernier pilier fondamental de la programmation : les fonctions !

28 min Débutant

Les fonctions et leur utilité

Qu'est-ce qu'une fonction ?

Vous ne vous en doutez peut-être pas, mais si vous avez déjà un peu programmé ou suivi les cours sur C# de ce site, vous avez déjà utilisé une ou plusieurs fonctions. Nous avons par exemple utilisé une fonction lorsque nous avons affiché quelque chose dans la console :

Console.WriteLine("Hello, world !");

La fonction en question se nomme 

WriteLine

et vous savez probablement déjà ce qu'elle fait : afficher une chaine de caractères dans la console. Vous avez donc déjà une bonne idée de ce qu'est une fonction : une chose que l'on peut appeler pour qu'elle fasse quelque chose.

L'utilité des fonctions

Remarquez que la définition que nous venons de donner au mot fonction n'est pas si différente de la définition même d'un programme. Une fonction peut donc être considérée comme un programme dans un programme. Un petit programme, donc, auquel les développeurs peuvent faire appel facilement pour construire une programme plus grand.

Se servir des fonctions revient donc à réutiliser des mini-programmes pour bâtir son propre programme. Ces mini-programmes peuvent avoir été codés par d'autres personnes, comme c'est le cas de la fonction

WriteLine

, mais également par vous même. Voyons ensemble comment utiliser des fonctions déjà existante en C# et comment en créer de nouvelles.

 

Utiliser des fonctions déjà existantes

Codez le moins possible !

Lorsque vous êtes programmeur, vous passez votre temps à utiliser des fonctions. Et devinez quoi ! La plupart du temps, les fonctions ne sont pas créées par vous ! Dans l'informatique réelle moderne, vous vous servirez très souvent de codes écrits par d'autres personnes. Tous les jours, des centaines de programmeurs développent et mettent à disposition des autres programmeurs des milliers de lignes de codes. Les fonctions sont justement la clé pour les réutiliser. C# (et son environnement .NET) fournissent déjà bon nombre de fonctions très utiles qui vous permettront déjà de faire de belles choses.

L'un des principes fondamentaux de la programmation est de ne pas se répéter et de ne pas réinventer la roue.

Se répéter signifie réécrire à plusieurs endroits un même code source source s'étendant sur plusieurs lignes. Réinventer la roue signifie recoder un programme que quelqu'un d'autre a déjà codé et mis à votre disposition. Les fonctions apportent une solution à ces deux problèmes.

Appeler des procédures

Nous connaissons déjà

Write

et

WriteLine

. Ces fonctions sont accessibles via le mot

Console

suivi d'un point

.

En C#, toutes les fonctions doivent être appelées par l'intermédiaire d'un mot ou plusieurs mots -séparé(s) par des points- qui est appelé leur domaine (scope en anglais). Dans le chapitre sur les boucles, nous avions par exemple vu la fonction

Sleep,

, à laquelle nous accédions comme ceci :

Threading.Thread.Sleep(1000);

Threading.Thread

est le domaine de la fonction

Sleep,

laquelle permet d'endormir le programme pendant un temps défini. De même,

Console

est le domaine des fonctions 

Write

et

WriteLine

.

Toutes ces fonctions servent juste à faire quelque chose : on ne s'en sert pas pour récupérer un résultat. Notez que les fonctions qui ne renvoient pas de résultats sont souvent nommées procédures.

Utiliser des fonctions qui renvoient un résultat

Le programme Square

C# met à notre disposition une foule d'autres fonctions concernant d'autres domaines que la console. Nous pouvons par exemple utiliser des fonctions permettant d'effectuer des calculs. Le domaine

Math

contient par exemple pas mal de fonctions pour effectuer des opérations avancées. Cette librairie est particulièrement pratique quand on crée des jeux vidéos !

Créons un petit programme exploitant quelques fonctions et appelons-le Square.

Ce programme demandera à l'utilisateur d'entrer un nombre et de choisir une opération à effectuer sur ce nombre : élever au carré ou calculer la racine carrée.

Demander quelque chose à l'utilisateur

Commençons par demander un nombre à l'utilisateur :

using System;

namespace Square
{
    class Program
    {
        static void Main(string[] args)
        {
            Console.Write("Entrez un nombre : ");
            string reponseUtilisateur = Console.ReadLine();
            
        }
    }
}

Nous utilisons ici deux fonctions, la fonction

WriteLine

et la fonction

ReadLine

.

La première affiche quelque chose dans la console et la deuxième nous permet de récupérer ce qui a été saisi dans la console. La première fonction est donc une procédure tandis que la deuxième  est une pure fonction.

Remarquez que nous utilisons ces fonctions différemment : WriteLine attend qu'on lui passe quelque chose en paramètre, c'est-à-dire qu'on écrive une valeur à l'intérieur de ses parenthèses. Ce n'est pas le cas de ReadLine. En y réfléchissant, c'est tout à fait logique puisque il faut bien que WriteLine sache ce qu'elle doit afficher tandis que ReadLine lira la réponse utilisateur au moment de l'exécution du programme.

Notez que

ReadLine

renvoie une chaine de caractères. Pour pouvoir exploiter ce qu'a entré l'utilisateur, je vais devoir transformer cette chaine en nombre (de type double, par exemple). Je vais pour cela utiliser une autre fonction, appelé

Parse

, laquelle est liée au domaine

Double

Cette fonction prend en paramètre une chaine de caractère et renvoie un nombre sous la forme d'un double.

// ...
double nombre = Double.Parse(reponseUtilisateur);
// ...

Ensuite, nous demandons à l'utilisateur d'entrer un calcul à effectuer :

Console.Write(
    "Quel calcul souhaitez vous effectuer : \n"
    + " 1. Élever au carré\n"
    + " 2. Calculer la racine carrée\n"
    + "Entrez votre choix : "
);
string souhaitUtilisateur = Console.ReadLine();

Effectuer une opération mathématique

En fonction de la réponse de l'utilisateur, on utilisera une fonction mathématique différente. Si la réponse est 1, nous écrirons le carré et si c'est 2, nous écrirons la racine carré. Pour calculer ces éléments, nous utiliserons les fonctions 

Math.Sqrt

-racine carrée- et 

Math.Pow

-fonction puissance- :

if (souhaitUtilisateur == "1")
{
    resultat = Math.Pow(nombre, 2);
}
else if (souhaitUtilisateur == "2")
{
    resultat = Math.Sqrt(nombre);
}
else
{
    Console.WriteLine("le choix entré n'est pas valide");
}

La fonction Sqrt renvoie la racine carrée du nombre passée en paramètre.

La fonction Pow prend, elle, deux paramètres, le premier est le nombre à élever, le deuxième est la puissance à laquelle on souhaite l'élever. Nous souhaitons élever nombre au carré, nous utiliserons donc 

Math.Pow(nombre,2)

!

Il ne nous reste plus qu'à afficher le résultat :

// ...
Console.WriteLine("Le choix résultat est " + resultat);
// ...

Nous obtenons le code suivant :

using System;

namespace Square
{
    class Program
    {
        static void Main(string[] args)
        {
            Console.Write("Entrez un nombre : ");
            string reponseUtilisateur = Console.ReadLine();
            double nombre = Double.Parse(reponseUtilisateur);

            Console.Write(
                "Quel calcul souhaitez vous effectuer : \n"
                + " 1. Élever au carré\n"
                + " 2. Calculer la racine carrée\n"
                + "Entrez votre choix : "
            );
            string souhaitUtilisateur = Console.ReadLine();

            double resultat = 0;

            if (souhaitUtilisateur == "1")
            {
                resultat = Math.Pow(nombre, 2);
            }
            else if (souhaitUtilisateur == "2")
            {
                resultat = Math.Sqrt(nombre);
            }
            else
            {
                Console.WriteLine("le choix entré n'est pas valide");
            }
            
            Console.WriteLine("Le choix résultat est " + resultat);
        }
    }
}

 

Notre programme se comporte bien comme attendu :

https://makeyourgame.fun/upload/uploads/2018/02/outsquare-300x43.png

Le truc en plus : utiliser l'auto-complétion

Si vous utilisez un éditeur de code un peu moderne, il est probable que celui-ci vous donne la possibilité d'utiliser l'auto-complétion. Par exemple, sous Visual Studio Code, vous avez la possibilité de taper Ctrl+Espace à la suite d'un domaine pour connaitre l'ensemble des fonctions disponibles dans le domaine. Par exemple, pour connaitre toutes les fonctions disponibles dans le domaine Math, j'écrirai Math. suivi de <Ctrl+Espace> et j'obtiendrai ceci :

https://makeyourgame.fun/upload/uploads/2018/02/autocomplete-300x113.png

Les fonctions, précédées d'un icône en forme de cube, s'affichent et peuvent être sélectionnées de façon à faire apparaître leurs informations à droite (paramètres à passer et éventuellement descriptif écrit). Cette fonctionnalité est extrêmement utile pour prendre en main du code qui n'est pas à nous !

 

Bien, nous savons maintenant comment utiliser des fonctions. Dans la dernière partie de ce cours, vous allez apprendre comment créer vos propres fonctions. Let's go !

Créer des fonctions

Nous avons vu comment utiliser des fonctions codées par d'autres. Voyons maintenant comment créer nos propres fonctions.

Une méthode dans un domaine

On l'a vu : les fonctions en C# sont toujours liées à un domaine. Ainsi, en C#, on parle plus volontiers de méthodes, que de fonctions. Ce domaine peut être une classe ou un objet. Nous verrons plus tard ce que sont les objets mais pour l'instant, concentrons-nous sur les méthodes liées à une classe car leur comportement est plus simple à appréhender quand on débute. Les méthodes liées à une classe sont dites statiques. Dans la fin de ce chapitre, les fonctions que nous créerons seront donc en réalité des méthodes statiques.

Notre première fonction

Créons un mini-projet appelé Hello Fonction dans lequel nous créerons nos premières fonctions. La première fonction que nous créerons sera très simple et affichera simplement "bonjour". Notre programme ressemble pour l'instant à ceci :

using System;

namespace Hello_Fonction
{
    class Program
    {
        static void Main(string[] args)
        {
            Console.WriteLine("Hello World!");
        }
    }
}

Jusqu'ici, nous avions ajouté du code uniquement à l'intérieur des deux accolades qui entourent le

Console.WriteLine

. Dans cette partie, nous allons enfin nous extraire de ces accolades et remonter d'un cran dans la hiérarchie ! Nous ajouterons du code à l'intérieur de la classe Programme, laquelle est annoncée à l'aide du mot-clé class. À l'intérieur de cette classe, nous créerons notre méthode statique, laquelle affichera simplement bonjour. Voici à quoi elle ressemble :

static void SayHello()
{
    
}

Pour dire à notre ordinateur que la méthode est statique, je dois mettre le mot-clé static devant la déclaration de ma fonction. Ensuite je dois renseigner le type de retour de ma fonction. Nous verrons tout à l'heure ce que c'est. Pour l'instant, nous mettons void. Ensuite, en troisième position, nous donnons à notre fonction un nom : elle s'appellera SayHello. Enfin, nous mettons un couple de parenthèses après le nom de la fonction. ce couple de parenthèses contiendra plus tard la liste des paramètres de la fonction. Nous allons aussi voir cela un peu plus loin.

Après la déclaration de ma fonction j'ouvre des accolades. Ces accolades contiennent le code qui sera exécuté lorsque je ferai appel à ma fonction. Pour l'instant, les accolades ne contiennent aucun code : ma fonction ne fait donc rien, à l'heure actuelle. Notez que le nom d'une méthode doit, par convention, commencer par une majuscule. Si ma fonction compte plusieurs mots, la première lettre de chaque doit également commencer par une majuscule.

Ajoutons du le code permettant de dire bonjour à l'utilisateur dans la méthode SayHello.

static void SayHello()
{
    Console.WriteLine("Bonjour, Utilisateur !");
}

Notre méthode doit bien dire : "Bonjour, Utilisateur !" Exécutons, notre programme pour le vérifier :

https://makeyourgame.fun/upload/uploads/2018/02/outbonjour1-300x12.png

Oups, notre programme n'exécute pas le code de notre fonction mais celui qui est juste au dessus. C'est tout à fait normal. Pour que le code d'une fonction soit exécuté, il faut l'appeler dans le code principal qui se trouve être celui  présent dans le Main, et dans lequel nous avions l'habitude de coder jusqu'à présent.

Appeler notre fonction

Appel simple

Pour appeler cette fonction, il suffit d'écrire son nom suivi d'un couple de parenthèse : 

SayHello()

Cette simplicité d'écriture est dûe au fait qu'on appelle cet fonction dans le même domaine que celui où elle est déclarée. Nous avons vu que dans le cas où nous appelons une fonction depuis un autre domaine, ce nom de domaine est à préciser avant l'appel à la fonction.

L'appel à une fonction est une instruction. Pour que la syntaxe soit correcte, je dois donc mettre un point virgule à la suite de l'appel à ma fonction. remplaçons notre "Hello World" par un appel à notre fonction. Cela nous donne :

static void Main(string[] args)
{
    SayHello();
}

static void SayHello()
{
    Console.WriteLine("Bonjour, Utilisateur !");
}

Lorsque on exécute ce code, cela fonctionne !

https://makeyourgame.fun/upload/uploads/2018/02/outbonjour2-300x12.png

Ajouter un paramètre à notre fonction

Notre fonction s'exécute bien ! Néanmoins, elle n'est pas très intéressante pour l'instant. Améliorons-la en lui donnant la possibilité de dire bonjour à n'importe quel utilisateur. Pour cela, notre fonction aura besoin de savoir à quel utilisateur elle doit dire bonjour. Pour lui transmettre cette information lorsque nous l'appelons, nous passerons ce que l'on appelle un paramètre ou encore un argument à notre fonction. Cette argument sera passé et récupéré à l'intérieur des parenthèses. Du côté de la déclaration de notre fonction, nous aurons ceci :

static void SayHello(string user)
{

Je dis à mon ordinateur que ma fonction prend un argument que j'appelle user et qui doit être de type string. À partir du moment où je fais cela, mon éditeur m'informe d'une erreur de syntaxe dans l'appel de ma fonction.

https://makeyourgame.fun/upload/uploads/2018/02/erreurbonjour.png

C'est normal, maintenant que ma fonction prend un paramètre, je dois fournir une valeur pour ce paramètre lors de mon appel. Appelons, notre utilisateur Gérard :

static void Main(string[] args)
{
    SayHello("Gérard");
}

Notre fonction attend une chaine de caractère,  Gérard est donc un string. Nous aimerions pouvoir dire bonjour à Josianne, ensuite :

static void Main(string[] args)
{
    SayHello("Gérard");
    SayHello("Josianne");
}

Testons :

https://makeyourgame.fun/upload/uploads/2018/02/outbonjour3-300x18.png

Exploiter le(s) paramètre(s) d'une fonction

Zut, pour l'instant, notre paramètre n'est pas pris en compte. Normal, puisque nous ne l'utilisons pas dans notre fonction. Réglons cela :

static void SayHello(string user)
{
    Console.WriteLine("Bonjour, " + user + " !");
}

Ici, nous remplaçons "Utilisateur" par la valeur passée en paramètre. Ainsi, notre fonction se comporte comme attendu !

https://makeyourgame.fun/upload/uploads/2018/02/outbonjour4-300x17.png

Nous commençons à percevoir un peu l'intérêt, n'est-ce-pas ? La même fonction (ou méthode statique) est appelée deux fois avec simplement des arguments différents et peut ainsi s'adapter à ce qu'on attend d'elle.

Cette méthode est un exemple de ce qu'on appelle une procédure : une fonction qui se contente de faire quelque chose mais qui ne retourne aucun résultat. Voyons maintenant les fonctions qui ne sont pas des procédures.

Retourner une valeur dans une fonction

La fonction factorielle

Dans cette partie, nous allons coder une fonction appelée Factorielle. Cette fonction est une fonction mathématique permettant de calculer la chose suivante :

  • Si l'argument qui lui est passé est inférieur à 1, alors elle renvoie la valeur 1.
  •        
  • Si l'argument est supérieur à 1, alors elle renvoie le produit du nombre et de tous les nombres qui le précède jusqu'à 1. Ainsi la factorielle de 4 est 24 car 24 = 4 * 3 * 2 * 1
  •  

Première ébauche

Créons un projet nommé Factorielle. Dans ce projet, nous allons d'abord écrire notre code à l'endroit habituel. Ensuite, nous rendrons notre code réutilisable en le mettant dans une fonction. Commençons par demander un nombre à l'utilisateur.

static void Main(string[] args)
{
    Console.WriteLine("Entrez un nombre : ");
    string reponseUtilisateur = Console.ReadLine();
    int nombre = Int32.Parse(reponseUtilisateur);
}

Le calcul de la factorielle peut se faire en utilisant une boucle for, comme ceci :

int fac = 1;
for(int i = 1; i <= nombre; i++){
    fac = fac * i;
}

fac contient à la fin de la boucle la factorielle du nombre saisi par l'utilisateur. Il ne nous reste qu'à afficher le résultat.

Console.WriteLine("La factorielle du nombre est : " + fac);

Amélioration

Supposez maintenant que notre programme ait à nouveau besoin de calculer une factorielle. Par exemple en redemandant à l'utilisateur un nombre et en effectuant à nouveau le calcul. Une idée serait de copier coller le code de cette façon :

static void Main(string[] args)
{
    Console.WriteLine("Entrez un nombre : ");
    string reponseUtilisateur = Console.ReadLine();
    int nombre = Int32.Parse(reponseUtilisateur);

    int fac = 1;
    for (int i = 1; i <= nombre; i++)
    {
        fac = fac * i;
    }

    Console.WriteLine("La factorielle du nombre est : " + fac);

    Console.WriteLine("Entrez un autre nombre : ");
    string reponseUtilisateur2 = Console.ReadLine();
    int nombre2 = Int32.Parse(reponseUtilisateur2);

    int fac2 = 1;
    for (int i = 1; i <= nombre2; i++)
    {
        fac2 = fac2 * i;
    }

    Console.WriteLine("La factorielle du nombre est : " + fac2);
}

fac

devient

fac2

,

reponseUtilisateur

devient

reponseUtilisateur2

et tout va bien : notre code fonctionne. Cependant, notre code a perdu en qualité. Pour deux raisons principales :

  • Notre code commence à devenir long et difficile à relire. Pas évident de comprendre ce qu'il fait au premier coup d’œil.
  •        
  • Notre code est plus difficile à maintenir : en effet, nous avons un code qui fait exactement la même chose à deux endroits différents. Si je me rends compte d'une erreur dans mon code, je serais obligé de corriger le problème à deux endroits. Imaginez l'ampleur du problème si on recopie le même code à 50 endroits différents sur un programme de 100 000 lignes ! Ingérable.
  •  

Pour améliorer la qualité de notre code, nous allons créer une fonction permettant de calculer et de récupérer la factorielle d'un nombre. Nous appellerons cette fonction fac. Voyez plutôt :

static void fac(int nombre) 
{
    int fac = 1;
    for (int i = 1; i <= nombre; i++)
    {
        fac = fac * i;
    }

    Console.WriteLine("La factorielle du nombre est : " + fac);
}

En utilisant cette fonction, je peux améliorer sensiblement mon code principal !

static void Main(string[] args)
{
    Console.WriteLine("Entrez un nombre : ");
    string reponseUtilisateur = Console.ReadLine();
    int nombre = Int32.Parse(reponseUtilisateur);

    fac(nombre);

    Console.WriteLine("Entrez un autre nombre : ");
    string reponseUtilisateur2 = Console.ReadLine();
    int nombre2 = Int32.Parse(reponseUtilisateur2);

    fac(nombre2);
}

Deuxième amélioration

Retourner un résultat

Cependant, en l'état, notre fonction n'est pas encore très satisfaisante car elle n'est pas très souple : elle ne peut que afficher "La factorielle du nombre est : " suivi de la valeur calculée. Pour être vraiment réutilisable dans une autre contexte, l'idéal serait de pouvoir récupérer la valeur calculée par la fonction. Pour cela, nous allons utiliser le mot clé return, lequel permet d'interrompre la fonction et de renvoyer un résultat à l'extérieur de celle-ci.

static void fac(int nombre) 
{
    int fac = 1;
    for (int i = 1; i <= nombre; i++)
    {
        fac = fac * i;
    }

    return fac; // ma fonction s'interrompt ici
    
    Console.WriteLine("La factorielle du nombre est : " + fac);
}

La fonction s'interrompt au niveau du return et renvoie le résultat à l'extérieur. La ligne suivante sera donc inutile car elle ne sera jamais exécutée. Nous pouvons l'enlever.

static void fac(int nombre) 
{
    int fac = 1;
    for (int i = 1; i <= nombre; i++)
    {
        fac = fac * i;
    }

    return fac; // ma fonction s'interrompt ici
}

À ce moment-là notre éditeur de code se réveille et nous annonce une erreur : Notre fonction revoie une valeur (qui est un entier) et annonce renvoyer un void, c'est-à-dire rien du tout. Il faut que j'annonce à mon ordinateur que ma fonction renvoie un entier. Pour cela, je dois modifier la façon dont je déclare ma fonction en remplaçant void par int.

static int fac(int nombre)

Récupérer un résultat

Maintenant que ma fonction renvoie un résultat, je peux le récupérer dans mon code principal. Dans une variable par exemple :

static void Main(string[] args)
{
    //...

    int fac1 = fac(nombre);

    //...

    int fac2 = fac(nombre2);
}

Je peux ensuite afficher ce résultat... ou bien faire tout autre chose avec !

static void Main(string[] args)
{
    // ...

    int fac1 = fac(nombre);

    Console.WriteLine("La factorielle du nombre " + nombre + " est " + fac1 + "!");

    // ...

    int fac2 = fac(nombre2);
    Console.WriteLine("La factorielle du nombre " + nombre2 + " est " + fac2 + "!");
}

 

Encore plus de fonction

Il est possible d'améliorer encore ce code ! En effet, ce dernier possède encore beaucoup de répétitions. Voici une version plus claire, plus lisible, et bien plus qualitative !

using System;

namespace Factorielle
{
    class Program
    {
        static void Main(string[] args)
        {

            int nombre = demanderNombre("Entrez un nombre");
            int fac1 = fac(nombre);

            Console.WriteLine("La factorielle du nombre " + nombre + " est " + fac1 + "!");

            int nombre2 = demanderNombre("Entrez un autre nombre");
            int fac2 = fac(nombre2);

            Console.WriteLine("La factorielle du nombre " + nombre2 + " est " + fac2 + "!");
        }

        static int demanderNombre(String phrase)
        {
            Console.WriteLine(phrase);
            string reponseUtilisateur = Console.ReadLine();
            int nombre = Int32.Parse(reponseUtilisateur);

            return nombre;
        }

        static int fac(int nombre)
        {
            int fac = 1;
            for (int i = 1; i <= nombre; i++)
            {
                fac = fac * i;
            }

            return fac;
        }
    }
}

 

 

Prenez le temps d'analyser ce code pour bien comprendre son fonctionnement.

Bien ! Nous en avons fini avec les fonctions et avec toutes les notions de bases. C'était long et parfois un peu fastidieux mais une fois que vous avez compris tout cela, vous êtes armés pour commencer à créer.

Si vous souhaitez approfondir le C# (ce que je vous recommande vivement), d'autres cours comme celui-ci suivront, lesquels porteront sur des notions plus avancées du langage telles que l'orienté objet. Restez connectés !

Vues: 132

Connectez-vous pour applaudir applause logo 1 claps

Validation du Tutoriel

Veuillez vous connecter ou créer un compte pour pouvoir valider ce tutoriel et ainsi gagner stardust et XP !

×