DTeK Learn logo

Tout savoir sur les fonctions en C#

16/11/2023

En C#, une fonction est définie comme une procédure nommée qui encapsule un ensemble d’instructions. Elle peut prendre des paramètres en entrée, effectuer des calculs, manipuler des données, et retourner des résultats… Les fonctions permettent de découper le code en morceaux logiques, ce qui facilite la gestion et la résolution des problèmes.

La réutilisabilité est l’un des principaux avantages des fonctions en C#. Plutôt que de copier-coller du code chaque fois qu’une tâche doit être effectuée, il est préférable de définir une fonction appropriée qui peut être appelée à plusieurs reprises, évitant ainsi la duplication inutile de code. Cette approche favorise également la maintenance du code, car les modifications ne doivent être apportées qu’à un seul endroit, ce qui se répercute sur toutes les occurrences de l’appel de cette fonction.

jeune développeur en reconversion professionnelle sur son ordinateur à son bureau

1. Qu’est-ce qu’une fonction en C# ?

Une fonction en C# est un bloc de code autonome qui effectue une tâche spécifique et peut être appelé à partir d’autres parties du programme pour exécuter cette tâche chaque fois que nécessaire. Les fonctions jouent un rôle fondamental dans l’organisation et la structuration du code, car elles permettent de découper un programme en tâches plus petites et plus gérables. Cela améliore la lisibilité, la maintenabilité et la réutilisabilité du code, réduisant ainsi la duplication et facilitant la résolution des problèmes.

Une fonction en C# peut prendre des paramètres en entrée, qui sont des valeurs transmises à la fonction pour qu’elle les traite. Ces paramètres permettent à la fonction d’effectuer des calculs et des opérations en utilisant des données spécifiques fournies par l’appelant. En outre, une fonction peut renvoyer une valeur en sortie, ce qui est très utile lorsque l’on souhaite obtenir un résultat ou une donnée calculée après l’exécution de la fonction.

Pour définir une fonction en C#, il faut spécifier son nom, les types et les noms des paramètres (s’il y en a), le type de valeur renvoyée (s’il y en a), et enfin, le bloc de code à exécuter lors de l’appel de la fonction. Une fois définie, une fonction peut être appelée de multiples fois depuis différentes parties du programme, favorisant ainsi la modularité et la flexibilité du code.

Les fonctions en C# peuvent être statiques ou non statiques. Les fonctions statiques appartiennent à une classe plutôt qu’à une instance spécifique de la classe et peuvent être appelées directement via la classe. En revanche, les fonctions non statiques, également appelées méthodes, sont liées à une instance spécifique de la classe et peuvent accéder aux données de l’objet sur lequel elles sont appelées.

2. Les différents types de fonctions en C#

Il existe plusieurs types de fonctions C#, chacun ayant des caractéristiques spécifiques. Comprendre ces différents types de fonctions est essentiel pour choisir la bonne approche lors de la conception de tes applications.

 

2.1 Fonctions sans valeur de retour (void)

Les fonctions sans valeur de retour, également appelées fonctions void, ne renvoient aucune valeur en sortie. Elles sont utilisées pour effectuer des opérations qui n’ont pas besoin de retourner une donnée. Par exemple, une fonction void peut être utilisée pour afficher un message à l’écran, effectuer une opération de mise à jour, ou simplement exécuter une séquence d’instructions sans renvoyer de résultat.

public void AfficherMessage(string message) {
    Console.WriteLine(message);
}

2.2 Fonctions avec valeur de retour

Contrairement aux fonctions void, les fonctions avec valeur de retour renvoient un résultat après avoir été exécutées. Elles sont utilisées pour effectuer des calculs ou des opérations qui nécessitent de renvoyer un résultat spécifique à l’appelant.

public int Somme(int a, int b) {
    return a + b;
}

2.3 Fonctions statiques

Les fonctions statiques sont liées à la classe plutôt qu’à une instance spécifique de la classe. Elles peuvent être appelées directement via la classe, sans avoir besoin de créer une instance de celle-ci. Les fonctions statiques sont souvent utilisées pour des opérations indépendantes de l’état de l’objet, comme des utilitaires ou des méthodes d’aide.

public static double ConvertirEnMiles(double kilometres) {
    return kilometres * 0.621371;
}

2.4 Fonctions non statiques (Méthodes)

Les fonctions non statiques, communément appelées méthodes, sont liées à une instance spécifique de la classe et peuvent accéder aux données de l’objet sur lequel elles sont appelées. Elles sont utilisées pour effectuer des opérations spécifiques liées à l’objet et dépendantes de son état.

public class CompteBancaire {
    private double solde;
    public void DeposerArgent(double montant) {
        solde += montant;
    }
}

2.5 Fonctions récursives

Une fonction récursive est une fonction qui s’appelle elle-même dans son propre corps. Cela permet de résoudre des problèmes de manière itérative en les décomposant en sous-problèmes plus simples.

public int Factorielle(int n) {
    if (n == 0) return 1;
    else return n * Factorielle(n – 1);
}

En comprenant les différents types de fonctions en C#, tu pourras choisir la meilleure approche pour résoudre efficacement les problèmes spécifiques de ton application. Chaque type de fonction a ses avantages et ses cas d’utilisation appropriés, il est donc important de les maîtriser pour créer un code clair, efficace et bien structuré.

3. Les paramètres de fonction en C#

Les paramètres de fonction jouent un rôle essentiel dans la communication entre le code appelant et la fonction elle-même. Ils permettent de transmettre des données ou des valeurs spécifiques à une fonction afin qu’elle puisse les traiter et effectuer des opérations en utilisant ces données. En C#, les paramètres de fonction peuvent être de différents types et peuvent également être facultatifs, ce qui offre une grande flexibilité lors de la conception d’une fonction.

 

3.1 Déclaration des paramètres

Pour déclarer des paramètres dans une fonction en C#, tu dois spécifier le type de données attendu suivi du nom du paramètre entre parenthèses lors de la définition de la fonction. Tu peux déclarer plusieurs paramètres en les séparant par des virgules.

public void AfficherMessage(string message, int repetitions)
{
    for (int i = 0; i < repetitions; i++)
    {
        Console.WriteLine(message);
    }
}

3.2 Passage de valeurs aux paramètres

Lorsque tu appelles une fonction avec des paramètres, tu dois fournir les valeurs correspondantes aux paramètres attendus. Ces valeurs peuvent être littérales, des variables ou des expressions.

string texte = « Hello, world! »;
int nombreRepetitions = 3;
AfficherMessage(texte, nombreRepetitions);

Dans cet exemple, la fonction AfficherMessage est appelée avec les paramètres texte et nombreRepetitions, qui sont respectivement la valeur de la variable texte et nombreRepetitions. La fonction affichera alors le message « Hello, world! » trois fois.

 

3.3 Paramètres facultatifs

En C#, tu peux définir des paramètres facultatifs en leur attribuant une valeur par défaut lors de leur déclaration. Les paramètres facultatifs permettent à une fonction d’être appelée sans fournir une valeur pour ces paramètres, car ils utiliseront la valeur par défaut définie dans la déclaration de la fonction.

public void AfficherMessage(string message, int repetitions = 1) {
    for (int i = 0; i < repetitions; i++) {
        Console.WriteLine(message);
    }
}

Dans cet exemple, le paramètre repetitions a une valeur par défaut de 1. Ainsi, si la fonction AfficherMessage est appelée sans fournir la valeur pour repetitions, elle sera exécutée une seule fois.

 

3.4 Paramètres de type générique

En C#, tu peux également utiliser des paramètres de type générique pour créer des fonctions qui acceptent des arguments de types variés. Les paramètres de type générique permettent d’écrire des fonctions réutilisables qui peuvent travailler avec différents types de données.

public void AfficherElement<T>(T element) {
    Console.WriteLine(element);
}

Dans cet exemple, la fonction AfficherElement est définie avec un paramètre de type générique T. Cela permet à la fonction d’afficher n’importe quel type de données, qu’il s’agisse d’une chaîne de caractères, d’un nombre ou d’un objet complexe.

 

En utilisant judicieusement les paramètres de fonction en C#, tu peux créer des fonctions polyvalentes et flexibles qui peuvent être réutilisées dans différentes parties de votre code. Les paramètres permettent également de rendre vos fonctions plus modulaires et faciles à entretenir, en les rendant capables de traiter des données spécifiques fournies par l’appelant.

4. La portée des variables en C#

La portée des variables fait référence à la visibilité et à la disponibilité d’une variable dans différentes parties du code. En C#, la portée d’une variable est déterminée par l’endroit où elle est déclarée et elle peut être globale, locale ou de paramètre.

 

4.1 Variables locales

Les variables locales sont déclarées à l’intérieur d’un bloc de code, tel qu’une fonction, une boucle ou une structure conditionnelle. Elles sont accessibles uniquement à l’intérieur de ce bloc et ne peuvent pas être utilisées en dehors. La portée d’une variable locale se limite au bloc dans lequel elle est déclarée.

public void ExemplePorteeVariables() {
    int x = 10; // Variable locale x
    if (x > 5) {
        int y = 20; // Variable locale y
        Console.WriteLine(x + y); // x et y sont accessibles ici
    }
    Console.WriteLine(y); // Erreur : y n’est pas accessible ici car en dehors de son bloc de déclaration
}

Dans cet exemple, les variables x et y sont locales dans les blocs où elles sont déclarées. La variable x est accessible dans toute la fonction ExemplePorteeVariables, tandis que la variable y n’est accessible que dans le bloc if.

 

4.2 Variables globales

Les variables globales sont déclarées en dehors de toutes les fonctions, généralement au niveau du fichier de code source. Elles sont visibles de toutes les fonctions dans le fichier et ont une portée globale. Cela signifie que leur valeur est conservée même après la fin de l’exécution d’une fonction et peut être utilisée dans différentes parties du code.

public class ExemplePorteeVariables {
    int variableGlobale = 100; // Variable globale
    public void AfficherVariableGlobale() {
        Console.WriteLine(variableGlobale); // Accès à la variable globale
    }
    public void ModifierVariableGlobale() {
        variableGlobale = 200; // Modification de la variable globale
    }
}

Dans cet exemple, la variable variableGlobale est une variable globale définie au niveau de la classe ExemplePorteeVariables. Elle peut être utilisée et modifiée dans toutes les méthodes de la classe.

 

4.3 Variables de paramètre

Les variables de paramètre sont des variables déclarées dans la signature d’une fonction et utilisées pour recevoir les valeurs passées à la fonction lors de son appel. Les paramètres sont considérés comme des variables locales dans le corps de la fonction et ont une portée limitée à celle-ci.

public void Multiplier(int a, int b) {
    int resultat = a * b; // Variable locale « resultat » calculée à partir des paramètres a et b
    Console.WriteLine(resultat);
}

Dans cet exemple, a et b sont des paramètres de la fonction Multiplier. Ils sont utilisés localement pour effectuer le calcul et n’existent que dans le contexte de la fonction. Il est important de bien comprendre la portée des variables en C# pour éviter les erreurs et assurer une utilisation efficace de la mémoire. En choisissant soigneusement la portée appropriée pour tes variables, tu peux créer un code bien organisé, clair et éviter les conflits entre les noms de variables dans différentes parties du programme.

5. Les méthodes d’extension en C#

Les méthodes d’extension sont une fonctionnalité puissante introduite dans C# 3.0 qui permet aux développeurs d’ajouter de nouvelles fonctionnalités à des types existants sans avoir besoin de modifier la définition de ces types. Les méthodes d’extension améliorent la lisibilité du code, favorisent la réutilisabilité et offrent une approche élégante pour étendre les fonctionnalités de bibliothèques ou de classes de base sans les sous-classer.

 

5.1 Définition d’une méthode d’extension

Une méthode d’extension est définie comme une méthode statique dans une classe statique. La classe statique qui contient une ou plusieurs méthodes d’extension doit être déclarée comme statique et doit être définie dans un espace de noms approprié pour que les méthodes d’extension soient accessibles.

public static class MethodesExtensionString {
    public static string PremierLettreEnMajuscule(this string texte) {
        if (string.IsNullOrEmpty(texte)) return texte;
        return char.ToUpper(texte[0]) + texte.Substring(1);
    }
}

Dans cet exemple, nous définissons une classe statique MethodesExtensionString contenant une méthode d’extension PremierLettreEnMajuscule. Cette méthode permet de transformer la première lettre d’une chaîne de caractères en majuscule.

 

5.2 Utilisation des méthodes d’extension

Pour utiliser une méthode d’extension, il faut simplement importer le namespace où la classe contenant la méthode d’extension est définie, et ensuite appeler la méthode directement sur l’objet cible. Notez que la classe qui contient la méthode d’extension doit être importée avec un using dans le fichier où elle est utilisée.

using MonEspaceDeNoms; // Importation du namespace
string texte = « hello world »;
string texteMajuscule = texte.PremierLettreEnMajuscule(); // Utilisation de la méthode d’extension
Console.WriteLine(texteMajuscule); // Affiche « Hello world »

5.3 Contraintes des méthodes d’extension

Il existe certaines contraintes pour définir des méthodes d’extension. Les méthodes d’extension doivent être définies dans des classes statiques, et les paramètres des méthodes d’extension doivent être du type que tu souhaites étendre (dans l’exemple ci-dessus, nous avons étendu le type string).

 

5.4 Portée des méthodes d’extension

Les méthodes d’extension sont uniquement visibles si le namespace contenant la classe statique qui les définit est importé dans le fichier où elles sont utilisées. Cela signifie que les méthodes d’extension ne sont pas automatiquement accessibles dans tous les fichiers de ton projet.

 

En utilisant les méthodes d’extension en C#, tu peux étendre les fonctionnalités de classes existantes sans altérer leur définition, ce qui facilite la maintenance et la mise à jour de ton code. Cette approche favorise également la lisibilité du code en regroupant les méthodes associées dans des classes statiques dédiées.

6. La récursivité en C#

La récursivité est un concept où une fonction s’appelle elle-même pour résoudre un problème en le décomposant en sous-problèmes plus simples. En C#, la récursivité est un outil essentiel pour résoudre des problèmes répétitifs ou pour parcourir des structures de données complexes de manière itérative.

 

6.1 Fonctionnement de la récursivité

Pour qu’une fonction soit récursive, elle doit contenir un cas de base qui arrête l’appel récursif et une ou plusieurs étapes de récursion qui résolvent progressivement le problème jusqu’à atteindre le cas de base. Chaque appel récursif utilise une nouvelle instance de la fonction avec des paramètres différents pour résoudre un sous-problème.

public int Factorielle(int n) {
    if (n == 0) return 1; // Cas de base : la factorielle de 0 est 1
    else return n * Factorielle(n – 1); // Étape de récursion : appel récursif avec un sous-problème plus simple
}

Dans cet exemple, nous avons une fonction récursive Factorielle qui calcule la factorielle d’un nombre entier. La factorielle d’un nombre n est le produit de tous les entiers positifs inférieurs ou égaux à n. Nous avons un cas de base lorsque n est égal à 0, où nous retournons 1. Sinon, nous effectuons un appel récursif en multipliant n par la factorielle de n-1, résolvant ainsi progressivement le problème jusqu’à atteindre le cas de base.

6.2 La gestion de la pile d’appels

Lorsqu’une fonction récursive est appelée, chaque instance de la fonction est empilée dans la pile d’appels. Chaque appel récursif crée une nouvelle instance de la fonction avec ses propres variables locales. Lorsque le cas de base est atteint, les appels récursifs commencent à se résoudre un par un, désempilant les instances de la fonction de la pile jusqu’à ce que le résultat final soit obtenu.

 

6.3 Attention aux boucles infinies

Il est essentiel de veiller à ce qu’une fonction récursive atteigne toujours le cas de base. Si le cas de base n’est pas atteint, la fonction continuera à s’appeler elle-même indéfiniment, entraînant une boucle infinie et provoquant un débordement de la pile. Il est donc important de bien définir les cas de base et de s’assurer que la récursion se termine correctement.

 

6.4 Avantages de la récursivité

La récursivité peut simplifier la résolution de problèmes en les décomposant en sous-problèmes plus simples et en évitant les boucles complexes. Elle permet également de produire un code concis et élégant, ce qui facilite la compréhension et la maintenance du code.

 

6.5 Inconvénients de la récursivité

La récursivité peut être coûteuse en termes de performance, car chaque appel récursif crée une nouvelle instance de la fonction et empile des variables locales dans la pile d’appels. De plus, une récursion excessive peut entraîner un débordement de la pile, surtout lorsque le problème à résoudre est très complexe.

 

En utilisant la récursivité avec prudence, tu peux résoudre efficacement des problèmes répétitifs et itératifs, ce qui facilite la conception de code élégant et bien structuré. La récursivité est une technique puissante qui enrichit l’arsenal du développeur et permet de résoudre une grande variété de problèmes de manière élégante et concise.

QCM

Testez vos connaissances sur ce sujet

TL;DR

Nous avons appris qu’il existe plusieurs types de fonctions en C#, dont les fonctions sans valeur de retour (void) qui n’ont pas besoin de renvoyer de données, les fonctions avec valeur de retour qui retournent des résultats après leur exécution, les fonctions statiques liées à la classe plutôt qu’à une instance spécifique, et les fonctions non statiques (méthodes) liées à une instance spécifique de la classe.

Les paramètres de fonction ont également été abordés en détail, montrant comment ils permettent de transmettre des données à une fonction pour qu’elle les traite, facilitant ainsi la personnalisation des opérations effectuées par la fonction.

Nous avons également exploré les méthodes d’extension, qui permet d’ajouter de nouvelles fonctionnalités à des types existants sans les modifier. Les méthodes d’extension offrent une approche élégante pour étendre les fonctionnalités des classes de base, améliorant ainsi la réutilisabilité du code.

Enfin, nous avons plongé dans le monde de la récursivité, une technique puissante qui permet de résoudre des problèmes de manière répétitive en les décomposant en sous-problèmes plus simples. Nous avons découvert le fonctionnement de la récursivité, les précautions à prendre pour éviter les boucles infinies, ainsi que ses avantages et inconvénients.