Surcharge de méthodes (Overloading)
La surcharge permet de définir plusieurs méthodes avec le même nom mais des paramètres différents. Le compilateur choisit la bonne version selon les arguments fournis.
Exemple de surcharge
class Calculatrice
{
public int Additionner(int a, int b)
{
return a + b;
}
public int Additionner(int a, int b, int c)
{
return a + b + c;
}
public double Additionner(double a, double b)
{
return a + b;
}
public int Additionner(params int[] nombres)
{
int somme = 0;
foreach (int nombre in nombres)
{
somme += nombre;
}
return somme;
}
}
static void TestSurcharge()
{
Calculatrice calc = new Calculatrice();
Console.WriteLine(calc.Additionner(5, 3));
Console.WriteLine(calc.Additionner(5, 3, 2));
Console.WriteLine(calc.Additionner(5.5, 3.2));
Console.WriteLine(calc.Additionner(1, 2, 3, 4, 5));
}
Paramètres optionnels et nommés
Paramètres optionnels
Les paramètres optionnels ont une valeur par défaut et peuvent être omis lors de l'appel.
class GestionnaireEmail
{
public void EnvoyerEmail(
string destinataire,
string sujet,
string corps,
bool avecCopie = false,
int priorite = 3
)
{
Console.WriteLine($"Envoi à {destinataire}");
Console.WriteLine($"Sujet: {sujet}");
Console.WriteLine($"Corps: {corps}");
Console.WriteLine($"Copie: {avecCopie}, Priorité: {priorite}");
}
}
static void TestParametresOptionnels()
{
GestionnaireEmail gestionnaire = new GestionnaireEmail();
gestionnaire.EnvoyerEmail("user@example.com", "Test", "Message", true, 5);
gestionnaire.EnvoyerEmail("user@example.com", "Test", "Message");
gestionnaire.EnvoyerEmail(
corps: "Message important",
destinataire: "admin@example.com",
sujet: "Urgent",
priorite: 1
);
}
Paramètre params
Le mot-clé params permet de passer un nombre variable d'arguments sous forme de tableau.
class OperationsMath
{
public int Maximum(params int[] nombres)
{
if (nombres.Length == 0)
throw new ArgumentException("Au moins un nombre requis");
int max = nombres[0];
foreach (int nombre in nombres)
{
if (nombre > max)
max = nombre;
}
return max;
}
public string Concatener(string separateur, params string[] mots)
{
return string.Join(separateur, mots);
}
}
static void TestParams()
{
OperationsMath ops = new OperationsMath();
Console.WriteLine(ops.Maximum(5));
Console.WriteLine(ops.Maximum(5, 3, 9, 2));
Console.WriteLine(ops.Maximum(12, 7, 20, 15, 8));
Console.WriteLine(ops.Concatener("-", "a", "b", "c"));
}
Méthodes d'extension
Les méthodes d'extension permettent d'ajouter de nouvelles méthodes à des types existants sans modifier leur code source.
static class ExtensionsString
{
public static int CompterMots(this string texte)
{
if (string.IsNullOrWhiteSpace(texte))
return 0;
return texte.Split(new[] { ' ', '\t', '\n' },
StringSplitOptions.RemoveEmptyEntries).Length;
}
public static string Capitaliser(this string texte)
{
if (string.IsNullOrEmpty(texte))
return texte;
return char.ToUpper(texte[0]) + texte.Substring(1);
}
public static string Inverser(this string texte)
{
char[] tableau = texte.ToCharArray();
Array.Reverse(tableau);
return new string(tableau);
}
}
static void TestExtensions()
{
string phrase = "bonjour le monde";
Console.WriteLine($"Nombre de mots: {phrase.CompterMots()}");
Console.WriteLine($"Capitalisé: {phrase.Capitaliser()}");
Console.WriteLine($"Inversé: {phrase.Inverser()}");
string resultat = phrase.Capitaliser().Inverser();
Console.WriteLine($"Capitalisé puis inversé: {resultat}");
}
Modificateurs de paramètres: ref, out, in
Paramètre ref
Permet de passer une référence à une variable. La variable doit être initialisée avant l'appel.
static void Echanger(ref int a, ref int b)
{
int temp = a;
a = b;
b = temp;
}
static void TestRef()
{
int x = 10, y = 20;
Console.WriteLine($"Avant: x={x}, y={y}");
Echanger(ref x, ref y);
Console.WriteLine($"Après: x={x}, y={y}");
}
Paramètre out
Similaire à ref, mais la variable n'a pas besoin d'être initialisée. La méthode DOIT assigner une valeur.
static bool DiviserEnQuotientEtReste(int dividende, int diviseur,
out int quotient, out int reste)
{
if (diviseur == 0)
{
quotient = 0;
reste = 0;
return false;
}
quotient = dividende / diviseur;
reste = dividende % diviseur;
return true;
}
static void TestOut()
{
if (DiviserEnQuotientEtReste(17, 5, out int q, out int r))
{
Console.WriteLine($"17 / 5 = {q} reste {r}");
}
}
Paramètre in
Passe une référence en lecture seule (utile pour optimiser les performances avec de grandes structures).
struct GrandeStructure
{
public int Valeur1 { get; set; }
public int Valeur2 { get; set; }
}
static int Calculer(in GrandeStructure structure)
{
return structure.Valeur1 + structure.Valeur2;
}
Exercice pratique
Créez un système de gestion de bibliothèque utilisant les concepts avancés.
using System;
using System.Collections.Generic;
using System.Linq;
class Livre
{
public string Titre { get; set; }
public string Auteur { get; set; }
public int Annee { get; set; }
public bool EstEmprunte { get; set; }
public override string ToString()
{
return $"'{Titre}' par {Auteur} ({Annee}) - {(EstEmprunte ? "Emprunté" : "Disponible")}";
}
}
static class ExtensionsBibliotheque
{
public static IEnumerable<Livre> Disponibles(this IEnumerable<Livre> livres)
{
return livres.Where(l => !l.EstEmprunte);
}
public static IEnumerable<Livre> ParAuteur(this IEnumerable<Livre> livres, string auteur)
{
return livres.Where(l => l.Auteur.Contains(auteur, StringComparison.OrdinalIgnoreCase));
}
}
class Bibliotheque
{
private List<Livre> livres = new List<Livre>();
public void Ajouter(string titre, string auteur, int annee)
{
livres.Add(new Livre { Titre = titre, Auteur = auteur, Annee = annee });
Console.WriteLine($"✅ Livre '{titre}' ajouté");
}
public void Ajouter(Livre livre)
{
livres.Add(livre);
Console.WriteLine($"✅ Livre '{livre.Titre}' ajouté");
}
public void AjouterPlusieurs(params Livre[] nouveauxLivres)
{
livres.AddRange(nouveauxLivres);
Console.WriteLine($"✅ {nouveauxLivres.Length} livres ajoutés");
}
public List<Livre> Rechercher(
string titre = null,
string auteur = null,
int? anneeMin = null,
bool uniquementDisponibles = false
)
{
var resultats = livres.AsEnumerable();
if (!string.IsNullOrEmpty(titre))
resultats = resultats.Where(l => l.Titre.Contains(titre, StringComparison.OrdinalIgnoreCase));
if (!string.IsNullOrEmpty(auteur))
resultats = resultats.Where(l => l.Auteur.Contains(auteur, StringComparison.OrdinalIgnoreCase));
if (anneeMin.HasValue)
resultats = resultats.Where(l => l.Annee >= anneeMin.Value);
if (uniquementDisponibles)
resultats = resultats.Disponibles();
return resultats.ToList();
}
public bool Emprunter(string titre, out string message)
{
var livre = livres.FirstOrDefault(l =>
l.Titre.Equals(titre, StringComparison.OrdinalIgnoreCase));
if (livre == null)
{
message = $"❌ Livre '{titre}' non trouvé";
return false;
}
if (livre.EstEmprunte)
{
message = $"❌ '{titre}' est déjà emprunté";
return false;
}
livre.EstEmprunte = true;
message = $"✅ Vous avez emprunté '{titre}'";
return true;
}
public void AfficherTous()
{
Console.WriteLine($"\n📚 Bibliothèque ({livres.Count} livres):");
foreach (var livre in livres)
{
Console.WriteLine($" {livre}");
}
}
}
class Program
{
static void Main()
{
Console.WriteLine("=== Système de Gestion de Bibliothèque ===\n");
Bibliotheque biblio = new Bibliotheque();
biblio.Ajouter("1984", "George Orwell", 1949);
biblio.Ajouter(new Livre
{
Titre = "Le Petit Prince",
Auteur = "Antoine de Saint-Exupéry",
Annee = 1943
});
biblio.AjouterPlusieurs(
new Livre { Titre = "Dune", Auteur = "Frank Herbert", Annee = 1965 },
new Livre { Titre = "Foundation", Auteur = "Isaac Asimov", Annee = 1951 },
new Livre { Titre = "Neuromancer", Auteur = "William Gibson", Annee = 1984 }
);
biblio.AfficherTous();
Console.WriteLine("\n=== Tests d'emprunt ===");
if (biblio.Emprunter("1984", out string msg1))
Console.WriteLine(msg1);
else
Console.WriteLine(msg1);
if (biblio.Emprunter("1984", out string msg2))
Console.WriteLine(msg2);
else
Console.WriteLine(msg2);
Console.WriteLine("\n=== Recherches ===");
var resultats1 = biblio.Rechercher(auteur: "Asimov");
Console.WriteLine($"Livres d'Asimov: {resultats1.Count}");
var resultats2 = biblio.Rechercher(anneeMin: 1960, uniquementDisponibles: true);
Console.WriteLine($"Livres après 1960 disponibles: {resultats2.Count}");
Console.WriteLine("\n=== Méthodes d'extension ===");
var tousLivres = biblio.Rechercher();
var disponibles = tousLivres.Disponibles();
Console.WriteLine($"Livres disponibles: {disponibles.Count()}");
foreach (var livre in disponibles)
{
Console.WriteLine($" {livre}");
}
Console.WriteLine("\n=== Programme terminé ===");
}
}