C# (prononcé « C sharp ») est l’un des langages les plus polyvalents et les mieux conçus du monde du développement logiciel. Créé par Anders Hejlsberg chez Microsoft et publié en 2000 avec le framework .NET, il a été conçu dès le départ pour combiner la puissance de C++ avec la productivité de Java, tout en corrigeant les défauts des deux. Aujourd’hui, C# et la plateforme .NET couvrent un périmètre remarquablement large : applications web avec ASP.NET Core, services cloud, applications bureau Windows (WPF, WinUI 3), applications mobiles cross-platform (MAUI), jeux vidéo (Unity), scripts d’automatisation et même WebAssembly via Blazor.
La migration de .NET Framework (Windows uniquement, closed-source) vers .NET Core puis .NET unifié (cross-platform, open-source) achevée avec .NET 5 en 2020 a transformé fondamentalement la position de C# dans l’industrie. .NET est aujourd’hui open-source (licence MIT), développé sur GitHub, et s’exécute nativement sur Linux, macOS et Windows — ce qui ouvre le déploiement sur serveurs Linux, containers Docker et plateformes cloud sans coût de licence.
Cet article couvre les fondamentaux de C# et .NET : l’histoire du langage, le système de types, la syntaxe moderne, l’écosystème NuGet, les frameworks d’application et les outils de développement. Chaque sous-sujet pratique dispose d’un tutoriel pas à pas dans cette série.
Histoire et évolution : de .NET Framework à .NET 9
C# 1.0 et .NET Framework 1.0 ont été lancés en février 2002. La plateforme .NET Framework était initialement limitée à Windows et proposait une approche de développement Windows-first très liée à l’écosystème Microsoft. Malgré cela, C# a rapidement gagné en popularité grâce à sa syntaxe claire, son système de types solide et la puissance de Visual Studio.
Les évolutions majeures du langage ont introduit des fonctionnalités transformatrices à chaque version : les génériques en C# 2.0 (2005), LINQ et les expressions lambda en C# 3.0 (2007), les méthodes asynchrones avec async/await en C# 5.0 (2012), les tuples et le pattern matching en C# 7.0 (2017), les types référence nullable en C# 8.0 (2019), les records en C# 9.0 (2020), et le pattern matching avancé, les raw string literals et les file-scoped namespaces en C# 10-11 (2021-2022).
La vraie révolution est venue avec .NET Core 1.0 en 2016, permettant pour la première fois de faire tourner C# nativement sur Linux et macOS. La transition s’est achevée avec .NET 5 (novembre 2020), qui unifie .NET Core et .NET Framework sous un seul nom et un cycle annuel de publication. Depuis, un nouveau .NET sort chaque novembre : .NET 6 LTS (novembre 2021), .NET 7 (novembre 2022), .NET 8 LTS (novembre 2023), .NET 9 (novembre 2024), .NET 10 LTS (novembre 2025).
En 2026, les versions recommandées sont :
- .NET 10 LTS (novembre 2025) — dernière version LTS, supportée jusqu’en novembre 2028. Choix recommandé pour tout nouveau projet en 2026. Introduit de nouveaux gains de performances JIT, l’amélioration des collection expressions C# 14 et plusieurs optimisations EF Core.
- .NET 8 LTS (novembre 2023) — version LTS supportée jusqu’en novembre 2026, recommandée pour les projets de production à long terme.
- .NET 9 (novembre 2024) — version STS (Standard Term Support, 24 mois suite à l’extension annoncée par Microsoft), introduit des optimisations significatives du JIT, des améliorations LINQ, et des nouveautés ASP.NET Core et Entity Framework Core.
- C# 13 — version courante du langage, livrée avec .NET 9. Améliore les params collections, les iterators async et les ref struct interfaces.
Le système de types C# : puissance et sécurité
Typage statique et fort
C# est un langage à typage statique et fort. Statique signifie que le type de chaque variable est connu et vérifié à la compilation. Fort signifie que les conversions implicites entre types incompatibles sont interdites — C# lève une erreur de compilation plutôt que de convertir silencieusement, contrairement à JavaScript. Cette rigueur au compile-time élimine toute une catégorie de bugs en production.
L’inférence de types via le mot-clé var (introduit en C# 3.0) permet d’omettre le type explicite quand il est évident du contexte — le compilateur le déduit automatiquement. Contrairement à Python ou JavaScript, var en C# est entièrement résolu à la compilation : la variable a bien un type fixe, l’inférence est juste syntaxique. Le mot-clé dynamic existe pour les scénarios rares nécessitant du typage dynamique (interopérabilité COM, code généré dynamiquement), mais son usage doit rester exceptionnel.
Types valeur et types référence
C# fait une distinction fondamentale entre types valeur et types référence, qui impacte directement les performances et le comportement des applications.
Les types valeur (int, double, bool, char, struct, enum) sont stockés directement dans la pile (stack) ou dans la structure qui les contient. L’affectation copie la valeur. Ils ne peuvent pas être null par défaut (sauf si déclarés int? — nullable value type).
Les types référence (class, string, array, delegate) sont stockés dans le tas (heap) géré par le GC. Une variable de type référence contient l’adresse mémoire de l’objet, pas l’objet lui-même. L’affectation copie la référence, pas l’objet — deux variables peuvent pointer vers le même objet.
Cette distinction est essentielle pour comprendre les performances en C#. Les struct (types valeur personnalisés) évitent les allocations heap et la pression sur le GC pour les petits objets fréquemment créés — DateTime, Guid, Vector3 (Unity) sont tous des structs pour cette raison.
Nullable reference types : la sécurité null en C# 8+
C# 8.0 a introduit les nullable reference types, activés par défaut dans les projets .NET 6+. Cette fonctionnalité distingue explicitement les références qui peuvent être null (string?) de celles qui ne le peuvent pas (string). Le compilateur émet des avertissements (warnings) quand une référence potentiellement null est utilisée sans vérification préalable, éliminant une grande partie des NullReferenceException au runtime.
La syntaxe moderne C# : expressivité et concision
Records : objets de données immuables
Les records (C# 9.0+) sont un nouveau type de classe conçu pour les objets de données immuables. Ils génèrent automatiquement l’égalité structurelle, ToString(), et le déconstruction. La syntaxe positionnelle est particulièrement concise :
// Record positionnel — C# 9.0+
public record Produit(int Id, string Nom, decimal Prix, int Stock);
// Instanciation
var p = new Produit(1, "Laptop ThinkPad", 850_000m, 10);
// Copie avec modification (expression "with")
var pSolde = p with { Prix = 720_000m };
// Égalité structurelle (compare les valeurs, pas les références)
var p2 = new Produit(1, "Laptop ThinkPad", 850_000m, 10);
Console.WriteLine(p == p2); // True — contrairement aux classes ordinaires
L’opérateur with crée une nouvelle instance du record en copiant toutes les propriétés de l’original et en remplaçant uniquement celles spécifiées — sans muter l’objet original. C’est le pattern « copy-on-write » de la programmation fonctionnelle rendu nativement expressif en C#. L’égalité structurelle (p == p2 retourne true) contraste avec le comportement des classes ordinaires où == compare les références (identité). Les records sont particulièrement adaptés aux DTOs (Data Transfer Objects), aux value objects de Domain-Driven Design et aux événements de domain.
Pattern matching avancé
Le pattern matching en C# permet de brancher sur la forme et le contenu des données avec une expressivité bien supérieure aux chaînes if/else ou switch classiques. C# 8 à 11 ont progressivement enrichi ces capacités :
// Pattern matching avec switch expression (C# 8+)
string ClassifierPrix(decimal prix) => prix switch
{
<= 10_000m => "Économique",
> 10_000m and <= 100_000m => "Milieu de gamme",
> 100_000m and <= 500_000m => "Premium",
_ => "Luxe" // _ = wildcard (cas par défaut)
};
// Pattern matching sur les types (C# 7+, amélioré en C# 9+)
string DecrireObjet(object obj) => obj switch
{
int n when n > 0 => $"Entier positif : {n}",
int n => $"Entier non positif : {n}",
string s => $"Chaîne de {s.Length} caractères",
null => "Valeur nulle",
_ => $"Objet de type {obj.GetType().Name}"
};
La switch expression (à distinguer de la switch statement classique) est une expression qui retourne une valeur — elle s’utilise directement dans une assignation ou un return. Le compilateur vérifie l’exhaustivité des patterns et émet un avertissement si un cas possible n’est pas couvert. Le pattern and permet de combiner des conditions de plage. Cette syntaxe réduit considérablement le code répétitif et améliore la lisibilité des branchements complexes sur des types ou des valeurs.
LINQ : Language Integrated Query
LINQ est l’une des fonctionnalités les plus distinctives de C#. Introduit en C# 3.0 (2007), il permet d’interroger et transformer des collections avec une syntaxe déclarative et type-safe, intégrée directement dans le langage. LINQ s’applique aux collections en mémoire (LINQ to Objects), aux bases de données via Entity Framework (LINQ to Entities, traduit en SQL), aux fichiers XML (LINQ to XML) et à tout objet implémentant IEnumerable<T> ou IQueryable<T>.
var produits = new List<Produit>
{
new(1, "Laptop", 850_000m, 10),
new(2, "Souris", 15_000m, 50),
new(3, "Clé USB", 8_000m, 200),
new(4, "Casque", 35_000m, 0)
};
// Syntaxe méthode (la plus utilisée en 2024)
var disponibles = produits
.Where(p => p.Stock > 0)
.OrderByDescending(p => p.Prix)
.Select(p => new { p.Nom, p.Prix, TTC = p.Prix * 1.18m })
.ToList();
// Syntaxe requête (SQL-like)
var rapport = from p in produits
where p.Prix > 10_000m
orderby p.Prix
select new { p.Nom, p.Prix };
// Agrégations
decimal totalStock = produits.Sum(p => p.Prix * p.Stock);
var plusCher = produits.MaxBy(p => p.Prix);
La syntaxe méthode est aujourd’hui préférée dans la grande majorité des bases de code C# modernes. Les opérateurs LINQ sont des méthodes d’extension sur IEnumerable<T> — ce mécanisme (extension methods) permet d’ajouter des méthodes à n’importe quel type sans modifier sa source. Where, Select, OrderBy retournent des IEnumerable<T> — la chaîne est évaluée paresseusement (lazy evaluation) et ne s’exécute qu’à l’appel de ToList(), ToArray(), First(), etc. MaxBy (méthode LINQ ajoutée dans .NET 6 — pas une feature du langage C#) retourne l’objet entier avec la valeur maximale, contrairement à Max qui retourne uniquement la valeur maximale.
L’écosystème .NET : NuGet, MSBuild et l’outillage
NuGet : le gestionnaire de paquets .NET
NuGet est le gestionnaire de paquets officiel de .NET, hébergeant plus de 350 000 paquets sur nuget.org. L’intégration est directe dans les fichiers .csproj (MSBuild) : ajouter une dépendance est une ligne XML ou une commande dotnet CLI. Les paquets sont téléchargés dans le cache local (~/.nuget/packages/ sur Linux/macOS) et restaurés automatiquement au build.
La CLI dotnet
La CLI dotnet est l’outil de ligne de commande central du développement .NET. Elle couvre la création de projets, la compilation, l’exécution, les tests, la publication et la gestion des dépendances NuGet. Ses commandes les plus utilisées au quotidien : dotnet new, dotnet run, dotnet build, dotnet test, dotnet publish, dotnet add package.
MSBuild et les fichiers .csproj
Les projets .NET sont définis par des fichiers .csproj au format XML MSBuild (SDK-style, simplifié depuis .NET Core). Un fichier .csproj minimal en SDK-style tient en 5 lignes et est lisible par n’importe quel développeur, contrairement aux anciens .csproj Visual Studio qui enumeraient tous les fichiers du projet.
Les frameworks d’application .NET
ASP.NET Core : le framework web cross-platform
ASP.NET Core est le framework web de Microsoft pour construire des APIs REST, des applications web MVC et Razor Pages, et des applications temps-réel avec SignalR. ASP.NET Core 10.0 (novembre 2025, LTS) est la version courante, succédant à ASP.NET Core 9.0 (novembre 2024, STS). Ses performances sont parmi les meilleures de l’industrie : le benchmark TechEmpower place régulièrement ASP.NET Core dans le top 5 des frameworks web en termes de requêtes par seconde pour les workloads HTTP.
Minimal APIs (introduit dans .NET 6) permet de définir des endpoints REST avec un minimum de code, sans les couches controller/model/service du MVC classique — idéal pour les microservices simples. Le MVC (Model-View-Controller) classique reste plus adapté aux applications avec plusieurs endpoints, validation complexe et architecture en couches.
Entity Framework Core : l’ORM .NET
Entity Framework Core (EF Core) est l’ORM officiel de Microsoft pour .NET. EF Core 9.0 (novembre 2024) supporte SQL Server, PostgreSQL (via Npgsql), SQLite, MySQL, et d’autres bases de données via des providers tiers. Comme Spring Data JPA dans l’écosystème Java, EF Core permet de travailler avec des objets C# sans écrire de SQL — le LINQ est traduit en requêtes SQL optimisées par le provider de base de données.
Blazor : C# dans le navigateur
Blazor est un framework UI web qui permet d’écrire des applications web interactives en C# plutôt qu’en JavaScript. Il existe en deux variantes : Blazor Server (le rendu se fait côté serveur, la communication passe par SignalR) et Blazor WebAssembly (le runtime .NET s’exécute directement dans le navigateur via WebAssembly). .NET 8 a introduit Blazor United, combinant les deux modes de rendu dans une seule application.
.NET MAUI : applications cross-platform
.NET MAUI (Multi-platform App UI) est le successeur de Xamarin.Forms pour le développement d’applications mobiles et desktop cross-platform en C#. Une base de code unique cible iOS, Android, macOS et Windows. MAUI est la solution Microsoft officielle pour les équipes souhaitant partager un maximum de code entre les plateformes mobiles.
Unity : développement de jeux en C#
Unity est le moteur de jeu le plus utilisé dans le monde, et il utilise C# comme langage de scripting principal. Les millions de développeurs Unity constituent une communauté C# massive, avec une culture de tutoriels, d’assets et de bibliothèques NuGet. Si le développement de jeux est votre domaine, C# est incontournable.
async/await : la concurrence moderne en C#
C# a été un précurseur dans la syntaxe async/await pour la programmation asynchrone, introduite en C# 5.0 en 2012. Ce modèle, adopté depuis par Python, JavaScript, Rust et Swift, permet d’écrire du code asynchrone avec la clarté du code synchrone. Task<T> et ValueTask<T> sont les primitives de la Task Parallel Library (TPL) sur lesquelles s’appuie async/await.
Dans ASP.NET Core, toutes les opérations I/O (appels HTTP, accès base de données, lecture/écriture fichiers) doivent être asynchrones pour permettre au serveur de traiter d’autres requêtes pendant l’attente. Un controller ASP.NET Core qui appelle une base de données doit retourner Task<IActionResult> et utiliser await sur les appels EF Core — sinon le thread est bloqué pendant la durée de l’appel, réduisant drastiquement la capacité de traitement concurrent.
Tutoriels de la série
- Installer .NET 9 et créer son premier programme C# pas à pas — Installation du SDK .NET 9, premiers programmes en ligne de commande, compréhension de la structure d’un projet .csproj, compilation et exécution.
- Créer une API REST avec ASP.NET Core pas à pas — API REST complète avec ASP.NET Core Minimal APIs et MVC : routes, validation, Entity Framework Core + SQLite, gestion des erreurs et tests.
Erreurs fréquentes à éviter
| Erreur | Cause | Solution |
|---|---|---|
| Utiliser .NET Framework pour un nouveau projet | Confusion avec .NET moderne | Cibler .NET 8 LTS ou .NET 9 — .NET Framework est en maintenance seule |
| Négliger les nullable reference types | Habitudes pré-C# 8 | Activer <Nullable>enable</Nullable> dans le .csproj et corriger les warnings |
Bloquer des threads avec .Result ou .Wait() |
Deadlock en contexte ASP.NET | Toujours await les Tasks — ne jamais bloquer synchroniquement |
Surcharger IDisposable sans using |
Fuites de ressources (connections DB, fichiers) | Utiliser le bloc using ou la déclaration using var (C# 8+) |
| Exécuter EF Core en dehors d’un scope DI | DbContext non scoped correctement |
Enregistrer le DbContext avec AddDbContext (scope par requête HTTP) |
| Exposer directement les entités EF Core dans l’API | Couplage couche persistance / API | Utiliser des DTOs avec AutoMapper ou mapping manuel |
FAQ
- Quelle différence entre .NET Framework et .NET (moderne) ?
- .NET Framework est l’ancienne plateforme Windows-only, sortie en 2002, dont la dernière version est .NET Framework 4.8.1 (en maintenance seule, sans nouvelles fonctionnalités). .NET (sans « Framework ») désigne la plateforme moderne, cross-platform, open-source, avec des versions annuelles depuis .NET 5 (2020). Tout nouveau projet en 2025 doit cibler .NET 8 LTS ou .NET 9.
- C# ou Java : quelle différence fondamentale en 2025 ?
- Les deux sont des langages à typage statique compilés sur une VM (CLR pour C#, JVM pour Java). C# a généralement été plus innovant dans l’évolution syntaxique (async/await 2012, pattern matching, records, nullable types, LINQ) et est souvent considéré comme plus expressif. Java a l’avantage d’un écosystème open-source plus ancien et d’une adoption enterprise massive. Le choix dépend souvent de l’environnement (Microsoft/Azure favorise C#, Linux/cloud-neutre favorise souvent Java/Spring).
- C# est-il performant ?
- Oui. .NET intègre un JIT (Just-In-Time compiler) hautement optimisé et le compilateur AOT (Ahead-of-Time) via Native AOT (.NET 8+) permet de produire des binaires natifs sans runtime .NET — démarrage sub-milliseconde et empreinte mémoire minimale. ASP.NET Core figure régulièrement dans le top 5 des benchmarks TechEmpower web frameworks. Le Span<T> et Memory<T> permettent de manipuler des zones mémoire contiguës sans allocation heap.
- C# fonctionne-t-il sur Linux et macOS en production ?
- Oui, depuis .NET Core 1.0 en 2016 et de façon mature depuis .NET 5 en 2020. La majorité des applications ASP.NET Core en production tournent sur Linux (containers Docker sur Kubernetes). Les images Docker officielles .NET sont disponibles sur Docker Hub (
mcr.microsoft.com/dotnet/aspnet) pour toutes les versions LTS. - Quel IDE pour développer en C# ?
- Visual Studio 2022 (Windows/macOS, Community gratuit) est le plus complet. VS Code avec l’extension C# Dev Kit (Microsoft) est une excellente option gratuite et cross-platform — recommandée pour Linux. JetBrains Rider est une alternative payante très appréciée, notamment sur macOS et Linux. La CLI
dotnetsuffit pour les projets simples et les pipelines CI/CD. - Quand utiliser Minimal APIs vs MVC dans ASP.NET Core ?
- Minimal APIs sont idéales pour les microservices simples, les APIs avec peu d’endpoints, les projets favorisant la clarté et la faible cérémonie. MVC Controller est préférable pour les APIs complexes avec de nombreux endpoints, des pipelines de validation avancés, des équipes habituées au pattern Controller/Service/Repository, et les applications nécessitant des filtres et middlewares granulaires par controller.
Tutoriels avancés .NET 10 et C# 14
Pour creuser la stack .NET moderne en 2026, cinq tutoriels pas-à-pas :
- C# 14 et .NET 10 : nouvelles fonctionnalités du langage — extension members, field, params Span
- EF Core 10 : vector, LeftJoin et filtres nommés — couche données moderne
- Worker Services .NET 10 en production — BackgroundService, Channels, queues
- gRPC avec ASP.NET Core 10 — services, streaming, clients typés
- BenchmarkDotNet en .NET 10 — mesurer la performance pas à pas