Cours C# Complet 💜
Les 12 chapitres essentiels — de la syntaxe de base à la POO avancée avec .NET, exemples et quiz
7. Héritage et polymorphisme
2. Variables et types de données
8. Interfaces et classes abstraites
3. Opérateurs et expressions
9. Gestion des exceptions
4. Structures conditionnelles
10. Collections et Generics
5. Les boucles
11. LINQ et Lambdas
6. POO : Classes et objets
12. Async/Await et C# moderne
🏠 Hub Programmation
🐍 Python
⚡ JavaScript
🔷 TypeScript
☁️ AWS Cloud Practitioner
Introduction et premier programme
using System;
namespace MonApp
// C# moderne — top-level statements (.NET 6+)
Console.WriteLine(« Bonjour le monde ! »);
Top-level statements (.NET 6+) : Plus besoin de classe Main ni de namespace. Le compilateur les génère automatiquement. Idéal pour les scripts et petits programmes. C'est le style recommandé pour commencer.
# https://dotnet.microsoft.com/download
# Créer un projet console
dotnet new console -n MonApp
cd MonApp
# Exécuter
dotnet run
# Compiler (produit un .dll ou .exe)
dotnet build
| Caractéristique | C# |
|---|---|
| Typage | Statique et fort — vérifié à la compilation |
| Paradigme | Orienté objet + fonctionnel |
| Runtime | .NET (CLR — Common Language Runtime) |
| Portabilité | Cross-platform depuis .NET Core / .NET 5+ |
| Usage | Web (ASP.NET), desktop (WPF, MAUI), jeux (Unity), cloud (Azure) |
| Convention | PascalCase pour les méthodes/propriétés, camelCase pour les variables locales |
C# vs Java : Syntaxe très similaire, mais C# évolue plus vite (propriétés, LINQ, async/await natif, pattern matching, records). Si vous connaissez JavaScript ou TypeScript, vous retrouverez beaucoup de concepts communs.
Variables et types de données
| Type | Taille | Plage | Exemple |
|---|---|---|---|
| byte | 1 octet | 0 à 255 | byte b = 42; |
| int | 4 octets | ±2.1 milliards | int n = 42; |
| long | 8 octets | ±9.2 × 10¹⁸ | long l = 42L; |
| float | 4 octets | ~7 chiffres | float f = 3.14f; |
| double | 8 octets | ~15 chiffres | double d = 3.14; |
| decimal | 16 octets | ~28 chiffres | decimal m = 3.14m; |
| bool | 1 bit | true / false | bool b = true; |
| char | 2 octets | Un caractère Unicode | char c = 'A'; |
decimal vs double : Utilisez decimal pour les calculs financiers (pas d'erreurs d'arrondi). double pour les calculs scientifiques (plus rapide). Suffixes obligatoires : f (float), m (decimal), L (long).
string nom = « Alice »;
// Interpolation (recommandée)
string salut = $ »Bonjour , vous avez ans »;
// Concaténation
string s = « Hello » + » World »;
// Verbatim string (pas d'échappement)
string path = @ »C:\Users\Alice\docs »;
// Raw string literal (C# 11+)
string json = « » »
« » »;
// Méthodes string
nom.Length // 5
nom.ToUpper() // « ALICE »
nom.ToLower() // « alice »
nom.Contains(« lic ») // true
nom.StartsWith(« A ») // true
nom.Substring(0, 3) // « Ali »
nom.Replace(« A », « a ») // « alice »
nom.Trim() // Supprime espaces
nom.Split(',') // string[]
string.IsNullOrEmpty(s) // null ou « »
string.IsNullOrWhiteSpace(s) // null, « » ou espaces
// var — inférence de type (le compilateur déduit)
var age = 25; // int
var liste = new List<string>(); // List
int age = null; // ❌ Erreur
int? age = null; // ✅ Nullable int
// Vérifier et utiliser
if (age.HasValue)
// ?? — valeur par défaut si null
int result = age ?? 0;
// ??= — assigner si null
age ??= 18;
// ?. — null-conditional (évite NullReferenceException)
string? ville = user?.Address?.City;
Opérateurs et expressions
+ – * / % ++ —
// Division entière (comme Java)
7 / 2 // 3 (pas 3.5 !)
7.0 / 2 // 3.5
// Comparaison
== != < > <= >=
// Logique
&& || !
// Ternaire
string status = age >= 18 ? « majeur » : « mineur »;
// Null-coalescing (??) et null-conditional (?.)
string nom = input ?? « Inconnu »;
int? len = text?.Length;
// is — vérifier le type (pattern matching)
if (obj is string s)
// as — cast sûr (retourne null si impossible)
string? s = obj as string;
Structures conditionnelles
if (age < 13) else if (age < 18) else
// Switch expression (C# 8+) — concis, retourne une valeur
string label = day switch
;
// Pattern matching dans switch (C# 9+)
string category = age switch
;
Switch expression (=>) : Beaucoup plus concis que le switch classique. Pas de break, retourne une valeur, et le compilateur vérifie que tous les cas sont couverts. Similaire au switch de JavaScript mais en mieux.
Les boucles
for (int i = 0; i < 5; i++)
// foreach — parcourir une collection
string[] fruits = ;
foreach (var fruit in fruits)
// while et do-while
while (i < 10)
do while (i < 10);
int[] nombres = ;
string[] noms = new string[3]; // Taille fixe
// Accès
nombres[0] // 1
nombres[^1] // 5 (dernier — Index from end)
nombres[1..3] // (Range — C# 8+)
// Propriétés et méthodes
nombres.Length // 5
Array.Sort(nombres);
Array.Reverse(nombres);
Array.IndexOf(nombres, 3);
Array.Exists(nombres, x => x > 3);
Arrays = taille fixe. Pour des collections dynamiques, utilisez List
POO : Classes et objets
Propriétés ≠ champs. En C#, on utilise des propriétés (avec get/set) au lieu d'accéder directement aux champs. C'est la convention universelle — pas besoin de getters/setters manuels comme en Python.
public class Person(string name, int age)
| Modificateur | Portée |
|---|---|
| public | Accessible partout |
| private | Classe uniquement (défaut pour les membres) |
| protected | Classe + sous-classes |
| internal | Même assembly (projet) |
| protected internal | Même assembly OU sous-classes |
| private protected | Même assembly ET sous-classes |
// required (C# 11) — oblige l'initialisation
public class Config
var config = new Config ;
Héritage et polymorphisme
public class Dog : Animal
// Polymorphisme
Animal a = new Dog(« Rex », « Labrador »);
a.Speak(); // « Rex : Wouf ! » — appelle la version Dog
public record Point(double X, double Y);
var p = new Point(3, 4);
p.X // 3
Console.WriteLine(p); // « Point »
// Comparaison par valeur (pas par référence)
var p2 = new Point(3, 4);
p == p2 // true (compare les valeurs)
// Copie avec modification (with expression)
var p3 = p with ; // Point
// record struct (C# 10) — type valeur
public readonly record struct Color(byte R, byte G, byte B);
Records = le standard pour les données. Ils génèrent automatiquement Equals, GetHashCode, ToString, et le déconstructeur. Préférez les records aux classes quand vous modélisez des données.
with pour copier.Interfaces et classes abstraites
public interface IValidatable
// Implémentation multiple
public class User : ISerializable, IValidatable
Convention C# : Les interfaces commencent par I (ISerializable, IDisposable, IEnumerable). C'est une convention forte de l'écosystème .NET.
public class Circle(double radius) : Shape
| Interface | Abstract class | |
|---|---|---|
| Héritage | Multiple | Simple uniquement |
| Constructeur | ❌ | ✅ |
| Champs | ❌ | ✅ |
| Usage | « Peut faire » (contrat) | « Est un » (base commune) |
Gestion des exceptions
catch (DivideByZeroException ex)
catch (Exception ex) // Attrape tout le reste
finally
// Lever une exception
public void SetAge(int age)
// Exception personnalisée
public class InsufficientFundsException : Exception
| Exception | Cause |
|---|---|
| NullReferenceException | Accès à un objet null |
| ArgumentException | Argument invalide |
| ArgumentNullException | Argument null |
| InvalidOperationException | Opération invalide pour l'état courant |
| IndexOutOfRangeException | Index hors limites |
| FormatException | int.Parse(« abc ») |
| IOException | Erreur lecture/écriture |
Collections et Generics
var noms = new List<string> ;
noms.Add(« Charlie »);
noms.Remove(« Bob »);
noms.Contains(« Alice »); // true
noms.Count // 2
noms[0] // « Alice »
// Dictionary
var ages = new Dictionary<string, int>
;
ages[« Alice »] // 25
ages.TryGetValue(« Eve », out var age); // false, age = 0
ages.ContainsKey(« Bob »); // true
// HashSet
var ids = new HashSet<int> ; //
// Queue
var queue = new Queue<string>(); // FIFO
var stack = new Stack<string>(); // LIFO
public T Max<T>(T a, T b) where T : IComparable<T>
=> a.CompareTo(b) > 0 ? a : b;
// Classe générique
public class Result<T>
// Contraintes where
// where T : class — type référence
// where T : struct — type valeur
// where T : new() — constructeur sans paramètre
// where T : IComparable — implémente l'interface
// where T : BaseClass — hérite de BaseClass
TryGetValue au lieu de l'indexeur direct pour éviter les KeyNotFoundException.LINQ et Lambdas
Func<int, int> double_ = x => x * 2;
Func<int, int, int> add = (a, b) => a + b;
Action<string> log = msg => Console.WriteLine(msg);
// Func = retourne une valeur
// Action = void (pas de retour)
// Predicate
// Where — filtrer
var pairs = nombres.Where(n => n % 2 == 0); //
// Select — transformer
var doubles = nombres.Select(n => n * 2); //
// Chaînage complet
var result = nombres
.Where(n => n > 3)
.Select(n => n * 2)
.OrderByDescending(n => n)
.Take(3)
.ToList(); //
// Opérations utiles
nombres.First() // 1
nombres.FirstOrDefault() // 1 (ou 0 si vide)
nombres.Last() // 10
nombres.Any(n => n > 5) // true
nombres.All(n => n > 0) // true
nombres.Count() // 10
nombres.Sum() // 55
nombres.Average() // 5.5
nombres.Min() // 1
nombres.Max() // 10
nombres.Distinct() // Dédupliquer
nombres.GroupBy(n => n % 2) // Grouper
nombres.ToDictionary(n => n, n => n * 2) // Dict
LINQ = le super-pouvoir de C#. Similaire aux Streams Java ou à filter/map de JavaScript, mais intégré directement dans le langage. Where = filter, Select = map.
map). Where = filtre les éléments (équivalent de filter).Async/Await et C# moderne
public async Task<string> FetchDataAsync(string url)
// void async = Task (pas de retour)
public async Task SaveAsync(string data)
// Parallèle
var task1 = FetchDataAsync(« url1 »);
var task2 = FetchDataAsync(« url2 »);
var results = await Task.WhenAll(task1, task2);
Convention : Toute méthode async se termine par Async (FetchDataAsync, SaveAsync). Utilisez toujours await — ne bloquez jamais avec .Result ou .Wait().
string content = await File.ReadAllTextAsync(« file.txt »);
string[] lines = await File.ReadAllLinesAsync(« file.txt »);
// Écrire
await File.WriteAllTextAsync(« out.txt », « Contenu »);
await File.AppendAllTextAsync(« log.txt », « Nouvelle ligne\n »);
// Vérifier
File.Exists(« file.txt »);
Directory.Exists(« folder »);
string Describe(object obj) => obj switch
;
// Property pattern
string GetDiscount(User user) => user switch
;
// List pattern (C# 11)
int[] arr = ;
if (arr is [1, .., 3])
✅ À FAIRE
• var quand le type est évident
• Propriétés auto (get; set;)
• Records pour les données
• LINQ pour les collections
• async/await pour l'I/O
• Switch expressions
• Pattern matching
• Nullable reference types activé
• using pour IDisposable
❌ À ÉVITER
• .Result et .Wait() (deadlocks)
• catch (Exception) vide
• public fields (utiliser propriétés)
• string concat en boucle (StringBuilder)
• goto
• dynamic sauf nécessité
• Ignorer les warnings nullable
• Thread direct (utiliser Task)
🏠 Hub Programmation
🐍 Cours Python
⚡ Cours JavaScript
🔷 Cours TypeScript
☁️ AWS Cloud Practitioner
Cours C# Complet — Des bases à C# 12 / .NET 8
Référence : Microsoft C# Docs | dotnet.microsoft.com

