C# et .NET

Qu’est-ce que C# ?

C# a été conçu spécialement pour la plateforme .NET Framework de Microsoft, et se prononce « See Sharp ».

Microsoft avait besoin d’un cadre de développement intégré unifié et entièrement orienté objet pour corriger les inconvénients des anciennes technologies. L’entreprise a donc entrepris de concevoir un nouvel environnement d’exécution du code ainsi qu’une chaîne complète d’outils de développement.

Après plus de 20 ans d’évolution, C# n’est plus un langage réservé à Windows : il est aujourd’hui compatible avec de multiples systèmes d’exploitation.

Aujourd’hui, C# associé à .NET forme une solution multiplateforme complète, permettant de concevoir des applications pour Windows, macOS, Linux et Android. Il constitue également l’environnement d’exécution privilégié de la plupart des systèmes cloud.

Grâce au soutien massif de Microsoft, C# bénéficie de mises à jour très régulières. La version 7 est sortie en 2022. Le langage reste compatible avec des codes écrits il y a 20 ans, tandis que les nouvelles versions proposent une syntaxe plus concise, plus élégante et des structures allégées. En 2026, nous disposons de la version 15.

Aperçu historique des versions de C# (extrait)

  • C# 1.0 (2001) : lancement public officiel
  • C# 2.0 (VS2005) : génériques, itérateurs, méthodes anonymes
  • C# 3.0 (VS2008) : méthodes d’extension, expressions Lambda, LINQ (requête intégrée au langage)
  • C# 4.0 (2010) : paramètres nommés / optionnels, type dynamique dynamic, bibliothèque de tâches parallèles TPL pour exploiter pleinement les processeurs multicœurs
  • C# 5.0 : prise en charge native des tâches asynchrones avec async/await
  • C# 6.0 : interpolation de chaînes, membres à corps d’expression, syntaxe simplifiée des propriétés
  • C# 7.0~7.3 : retours multiples via tuples, simplification des paramètres out, filtrage par motif, méthode Main asynchrone
  • C# 8.0/9.0/10.0 : enregistrements (types de référence immuables), instructions de niveau supérieur (sans Main obligatoire), méthodes d’interface par défaut, fonctions locales statiques, types libérables asynchrones, filtrage par motif sur l’ensemble du langage
  • C#11 (.NET7) : chaînes brutes, opérateurs mathématiques génériques, propriétés required
  • C#12 (.NET8) : constructeurs principaux, syntaxe abrégée des collections, tableaux en ligne
  • C#13 (.NET9) : propriétés partielles, indexeurs d’extension, variables ref locales dans les itérateurs
  • C#14 (.NET10) : alias génériques, filtrage profond des collections, sucre syntaxique SIMD

Windows reste la plateforme centrale de C#, mais grâce au .NET Runtime, le code s’exécute directement sur des systèmes comme Linux. On peut donc écrire une seule base de code pour la déployer sur plusieurs OS.

Le framework .NET

Le .NET Framework a été lancé pour la première fois en 2002.

Le .NET Framework résout les inconvénients des générations précédentes d’outils de développement ; ses principaux atouts sont :

  1. Prise en charge multi-dispositifs : fonctionne sur serveurs, ordinateurs, PDA, téléphones mobiles et autres matériels ;
  2. Conformité aux standards industriels : support natif des protocoles de communication universels XML, HTTP, SOAP, JSON, WSDL ;
  3. Bac à sable de sécurité : isole l’exécution des codes provenant de sources non fiables.

Les trois composants fondamentaux du .NET Framework

  1. CLR Common Language Runtime (environnement d’exécution) gère tout le cycle de vie des programmes : gestion de la mémoire et ramasse-miettes, validation de la sécurité du code, ordonnancement des threads, gestion des exceptions.
  2. Ensemble d’outils de développement environnements de développement intégrés, compilateurs .NET multilingues (C#/VB.NET/F#, etc.), débogueurs et technologies backend web comme ASP.NET/WCF.
  3. BCL Bibliothèque de classes de base (aussi appelée FCL Framework Class Library) contient une multitude de classes génériques préimplémentées que le développeur peut appeler directement.

Points d’amélioration de .NET par rapport au développement Windows traditionnel

Modèle orienté objet unifié

CLR, BCL et C# sont profondément intégrés et proposent un modèle OOP homogène. Les applications de bureau, mobiles, web et distribuées partagent le même paradigme de développement, avec une syntaxe et une logique cohérentes sur tous les appareils.

Ramasse-miettes automatique GC

Le CLR embarque nativement un ramasse-miettes qui libère automatiquement la mémoire des objets inutilisés. Le développeur n’a pas à libérer manuellement la mémoire ni à traquer les fuites mémoire, ce qui allège considérablement la maintenance.

Interopérabilité multidimensionnelle
  1. Échanges entre langages .NET : les classes écrites dans différents langages .NET peuvent s’appeler et s’hériter mutuellement ; la plateforme n’est pas liée à un unique langage de programmation ;
  2. Appel de plateforme P/Invoke : permet d’invoquer directement les interfaces des DLL natives Win32 écrites en C ;
  3. Compatibilité COM : les composants .NET et les composants COM traditionnels peuvent s’appeler dans les deux sens.

Déploiement simplifié : pas de dépendance au registre ; dans les cas minimaux, il suffit de copier les fichiers pour lancer le programme ;

Assemblys côte à côte : plusieurs versions d’une même DLL peuvent coexister sur un appareil. Chaque programme est lié à la version de bibliothèque avec laquelle il a été compilé, ce qui résout les conflits de versions de DLL.

Vérification de sûreté des types Le CLR (Common Language Runtime) contrôle obligatoirement les paramètres et les types de données. Même lors des échanges entre composants de langages différents, il garantit la sûreté des types et empêche tout accès mémoire illégal.

Une BCL fournie complète

De nombreuses classes utilitaires génériques sont intégrées nativement

  • Outils basiques pour les fichiers, chaînes de caractères, chiffrement et sécurité ;
  • Conteneurs de collections : listes, dictionnaires, tables de hachage ;
  • Outils de multithreading, synchronisation et parallélisme ;
  • Classes de lecture et d’écriture de documents XML
  • … et bien d’autres fonctionnalités

Toute la logique basique commune est préconçue : le développeur n’a qu’à écrire la logique spécifique à son métier, en réutilisant des outils éprouvés pour éviter de réinventer la roue.

Diagramme de flux d’un programme .NET : le code que vous écrivez est compilé en code intermédiaire IL. L’IL peut appeler les bibliothèques fournies par la BCL, puis est transmis au CLR pour exécution.

Relation entre C# et .NET

.NET Framework : une plateforme complète de développement et d’exécution composée de deux composants majeurs

  1. CLR (Common Language Runtime) : gère la mémoire du code, son exécution et les contrôles de sécurité
  2. BCL (Bibliothèque de classes de base) : vaste ensemble de code utilitaire générique (fichiers, réseau, interfaces graphiques, parallélisme, etc.)

C# : un langage de programmation conçu exclusivement pour la plateforme .NET, destiné à écrire du code exécutable sur le CLR

Outre C#, d’autres langages informatiques prennent en charge .NET, à l’instar de F# et VB.NET.

L’objectif du framework .NET est d’être multiplateforme et multilingue. Multiplateforme signifie fonctionner sur différents systèmes d’exploitation ; multilingue signifie que des composants développés dans des langages distincts peuvent interagir entre eux.

Compilation vers le Langage Intermédiaire Commun (CIL)

Le compilateur des langages .NET lit les fichiers de code source et génère des fichiers de sortie appelés assemblys

Il existe deux types d’assemblys : les exécutables (exe) ou les bibliothèques de liaison dynamique (DLL)

Le code contenu dans un assembly n’est pas du code machine natif du processeur, mais un code intermédiaire désigné sous le nom de Langage Intermédiaire Commun (Common Intermediate Language, CIL).

Un assembly contient principalement ces éléments :

  1. Les instructions CIL du programme
  2. Les métadonnées de tous les types définis dans le programme
  3. Les métadonnées décrivant les liens de référence vers d’autres assemblys externes

L’abréviation du langage intermédiaire a évolué au fil des versions de .NET, d’où des dénominations différentes selon les documents. Langage Intermédiaire (IL) et Langage Intermédiaire Microsoft (MSIL) désignent tous deux le CIL.

Compilation en code natif et exécution

Le CIL n’est pas converti en code machine natif à l’avance ; seule au lancement du programme, le CLR suit ces trois étapes :

  1. Vérifier les informations de sécurité de l’assembly
  2. Allouer la mémoire d’exécution
  3. Transmettre au compilateur JIT pour une compilation fragmentée en code natif
Mécanisme de compilation à la demande JIT

Seul le code qui sera exécuté est compilé, puis mis en cache pour réutilisation. Le code jamais appelé n’est pas compilé, et un même fragment de code ne subit la compilation qu’une seule fois.

Assembly (CIL + informations de types) → CLR (compilateur JIT) → Code natif → Services du système d’exploitation

Responsabilités de gestion du CLR

Après conversion du CIL en code natif, le CLR gère automatiquement : récupération de la mémoire inutilisée, contrôle des dépassements de tableau, validation des types de paramètres et gestion des exceptions.

Code managé et code non managé
  • Code managé : code écrit dans un langage .NET, dont l’exécution est supervisée par le CLR
  • Code non managé : non soumis au contrôle du CLR, par exemple les DLL natives Win32 en C/C++

Microsoft propose aujourd’hui la compilation AOT : il est possible de compiler directement le code C# en code natif, à l’instar du C++. On peut alors lancer l’exécutable EXE sans avoir installé le runtime .NET au préalable.

Outil NGen

Il précompile hors ligne les assemblys en images natives ; à l’exécution, l’étape JIT est ignorée, ce qui accélère le démarrage de l’application.

.NET Core AOT est la nouvelle génération de précompilation, capable de produire des exécutables natifs autonomes sans dépendance au runtime.

Assembly (Informations de type, CIL)
        ↓
Compilateur JIT
        ↓
Code natif
        ↓
Services du système d’exploitation

Quel que soit le langage du code source initial, tous suivent le même flux de compilation et d’exécution.

Chaque langage dispose de son propre compilateur : VB.NET a son compilateur dédié, C# le sien. Tous transforment leur code en CIL, le CIL passe par le JIT pour générer du code natif, lui-même exécuté par le processeur. C’est pourquoi les logiciels développés sous .NET nécessitent l’installation de l’environnement .NET, tout comme Java requiert le JRE.

flowchart TD
    subgraph Compile_Time
        A[C# Source] --> B[C# Compiler]
        B --> C[Assembly CIL]
        D[VB Source] --> E[VB Compiler]
        E --> C
        F[Xyz.NET Source] --> G[Xyz.NET Compiler]
        G --> C
    end

    subgraph Run_Time
        C --> H[JIT Compiler]
        H --> I[Native Code]
        I --> J[Operating System Services]
    end

Le schéma ci-dessus illustre le flux complet de compilation et d’exécution pour tous les langages.

Common Language Runtime (CLR)

Le composant central du .NET Framework est le CLR, qui se situe au-dessus du système d’exploitation et assure la gestion complète de l’exécution des programmes.

  • Ramasse-miettes automatique (GC)
  • Vérifications de sécurité et authentification via la Bibliothèque de classes de base (BCL)
  • Fournit de riches capacités de programmation, dont services web, services de données et bien d’autres fonctionnalités
flowchart TD
    subgraph Unmanaged_Code
        A[Non-.NET Program] --> OS[Operating System]
    end

    subgraph Managed_Code
        B[Assembly] --> CLR[Common Language Runtime]
        C[Assembly] --> CLR
        D[Assembly] --> CLR

        subgraph CLR[Common Language Runtime]
            M[Memory Management] --- E[Exception Handling]
            G[Garbage Collection] --- R[Reflection Services]
            J[JIT Compiler] --- L[Class Loader]
            S[Security Services]
        end

        CLR --> OS
    end

Infrastructure de Langage Commune (CLI)

Chaque langage de programmation embarque un ensemble de types natifs basiques pour représenter les entiers, nombres à virgule flottante, caractères et autres données.

Infrastructure de Langage Commune (CLI) est un ensemble de standards qui unifie l’ensemble des composants du .NET Framework en un système cohérent et interopérable.

Par exemple, le nombre de bits occupé par un entier est identique dans tous les langages compatibles.

flowchart TD
    subgraph CLI[CLI]
        CLR[Common Language Runtime] --- CLS[Common Language Specification]
        BCL[Base Class Library] --- MDS[Metadata Definition & Semantics]
        CTS[Common Type System] --- CIL[Common Intermediate Language]
    end

La plupart des développeurs n’ont pas besoin d’approfondir l’intégralité des spécifications de la CLI, mais il est indispensable de maîtriser le Système de Types Commun CTS et la Spécification de Langage Commun CLS.

CTS Système de Types Commun

  • Propose un jeu standardisé de types de données basiques aux propriétés fixes ;
  • Tous les types spécifiques à chaque langage .NET sont mappés sur un sous-ensemble de ces types standards ;
  • Tous les types héritent de la classe racine object ;
  • Le standard unifié permet aux types natifs du système et aux types définis par l’utilisateur de s’échanger entre n’importe quel langage .NET.

CLS Spécification de Langage Commun

Définit les règles unifiées que doivent respecter tous les langages compatibles avec .NET, couvrant les contraintes d’interlangage : types de données, constructeurs de classes, passage de paramètres, etc.

Différences entre .NET et .NET Framework

.NET est la plateforme multiplateforme moderne de Microsoft, tandis que .NET Framework est l’ancien runtime et bibliothèques limité exclusivement à Windows. Toutes les nouvelles fonctionnalités sont développées sur .NET ; .NET Framework est en mode maintenance et ne reçoit que des mises à jour de sécurité.

.NET est multiplateforme et constitue aujourd’hui la plateforme de développement principale de Microsoft. La suite de ce guide se concentrera sur lui.

Caractéristique.NET.NET Framework
Prise en charge des plateformesMultiplateforme (Windows, Linux, macOS, conteneurs, mobile via MAUI)Windows uniquement
StatutMises à jour continues (.NET 5 à .NET 10, sorties annuelles avec support LTS)Mode maintenance (4.8 est la version finale, uniquement des correctifs de sécurité)
PerformancesDémarrage plus rapide, débit supérieur, ramasse-miettes optimiséPerformances anciennes, dépendant des API Windows
Cas d’usageNouveaux projets : API web, microservices, cloud natif, bureau/mobile multiplateformeAnciens projets : Web Forms, WCF, Windows Workflow, etc.
DéploiementCompatible Docker, conteneurs et environnements cloudIncompatible conteneurs, dépendant de Windows Server
Langages pris en chargeC#, F#, VB.NET (multiplateforme)C#, VB.NET (Windows seulement)

Les écarts entre .NET et .NET Framework sont minimes. Les deux utilisent des langages comme C#, F# et VB.NET et conservent une syntaxe de base identique. La majeure partie du code C# que vous écrivez peut être compilée et exécutée à la fois sur .NET Framework et sur .NET (Core/5/6/7/8…).

Les différences portent essentiellement sur la disponibilité des bibliothèques de classes, pas sur la syntaxe.

Certaines technologies présentes dans .NET Framework comme WCF, Web Forms et Windows Workflow ont été supprimées ou remplacées dans le .NET moderne.

Le .NET moderne intègre des API récentes telles que Span<T>, ValueTask et Records, absentes de l’ancien .NET Framework.

Étant donné que .NET Framework est exclusivement Windows et que .NET est multiplateforme, certaines bibliothèques spécifiques à Windows ont été retirées de .NET. Par exemple, System.Drawing fonctionne sous Windows mais est marqué compatible Windows uniquement sur le .NET multiplateforme. Si vous avez besoin d’une bibliothèque de dessin sous .NET, vous ne pouvez pas utiliser System.Drawing et devrez recourir à des bibliothèques tierces comme SkiaSharp de Google.

Attention : ces différences concernent la couche framework ; au niveau du langage tel que C#, elles sont quasi nulles. La syntaxe C# reste identique sur les deux environnements. La vraie différence réside dans les bibliothèques de classes et l’environnement d’exécution, c’est-à-dire l’ensemble des API accessibles.

Laisser un commentaire

Votre adresse e-mail ne sera pas publiée. Les champs obligatoires sont indiqués avec *