Histoire du langage C#

Cet article fournit un historique de chaque version majeure du langage C#. L’équipe C# continue d’innover et d’ajouter de nouvelles fonctionnalités. L’état détaillé des fonctionnalités de langage, notamment celles prises en compte pour les versions à venir, est disponible dans le dépôt dotnet/roslyn sur GitHub.

Important

Le langage C# s’appuie sur des types et des méthodes dans ce que la spécification C# définit comme une bibliothèque standard pour certaines fonctionnalités. La plateforme .NET fournit ces types et ces méthodes dans des packages. Par exemple, le traitement des exceptions. Chaque instruction ou expressionthrow est vérifiée pour s’assurer de l’objet levé est dérivé de Exception. De même, chaque catch est vérifié pour assurer que le type intercepté est dérivé de Exception. Chaque version peut ajouter de nouvelles spécifications. Pour utiliser les dernières fonctionnalités de langage dans les environnements plus anciens, vous devrez peut-être installer des bibliothèques spécifiques. Ces dépendances sont décrites dans la page pour chaque version spécifique. Pour en savoir plus, consultez les relations entre le langage et la bibliothèque pour l’arrière-plan sur cette dépendance.

C# version 1.0

Quand vous revenez en arrière et regardez, C# version 1.0, publiée avec Visual Studio .NET 2002, ressemblait beaucoup à Java. Dans le cadre de ses objectifs de conception énoncés pour ECMA, il cherchait à être un « langage simple, moderne et universel orienté objet ». À l’époque, l’apparence de Java signifiait qu’elle a atteint ces objectifs de conception précoces.

Mais si vous repensez à C# 1.0 maintenant, cela peut vous donner le vertige. Il lui manquait des fonctionnalités asynchrones intégrées et certaines des fonctionnalités liées aux génériques qui sont aujourd’hui pour vous une évidence. En fait, il ne proposait pas du tout de génériques. Et LINQ ? Pas encore disponible. Il fallait attendre encore plusieurs années.

C# version 1.0 semblait dénué de fonctionnalités, par rapport à aujourd’hui. Vous vous retrouviez à écrire plus ou moins du code détaillé. Mais il faut bien commencer quelque part. C# version 1.0 était une alternative viable à Java sur la plateforme Windows.

Les principales fonctionnalités du langage C# 1.0 étaient les suivantes :

C# version 1.2

C# version 1.2 fournie avec Visual Studio .NET 2003. Cette version contenait quelques améliorations mineures du langage. La principale est que, à compter de cette version, le code était généré dans une boucle foreach (appelée Dispose) sur un IEnumerator quand ce IEnumerator implémentait IDisposable.

C# version 2.0

Les choses commencent alors à devenir intéressantes. Examinons certaines fonctionnalités majeures de C# 2.0, sorti en 2005, en même temps que Visual Studio 2005 :

D’autres fonctionnalités de C# 2.0 ajoutaient des capacités aux fonctionnalités existantes :

  • Accessibilité distincte des accesseurs Get/Set
  • Conversions de groupes de méthodes (délégués)
  • Classes statiques
  • Inférence de délégué

Alors que C# avait démarré en tant que langage orienté objet générique, C# version 2.0 a rapidement changé tout ça. En effet, maintenant que le langage existait, il s’agissait de s’attaquer à certains problèmes majeurs que rencontraient les développeurs. Et de s’y attaquer de manière significative.

Avec les génériques, les types et les méthodes peuvent fonctionner sur un type arbitraire tout en assurant quand même la cohérence des types. À titre d’exemple, un List<T> vous permet d’avoir List<string> ou List<int> et d’effectuer des opérations qui maintiennent la cohérence des types sur des chaînes ou entiers alors que vous itérez en leur sein. L’utilisation de génériques est préférable à la création d’un ListInt type qui dérive de ou à partir ArrayList de Object pour chaque opération.

C# version 2.0 a introduit les itérateurs. En bref, les itérateurs permettent d’examiner tous les éléments dans un List (ou d’autres types énumérables) avec une boucle foreach. Le fait de disposer d’itérateurs comme composants de premier ordre du langage en a considérablement amélioré la lisibilité et la capacité de raisonnement des utilisateurs vis-à-vis du code.

Pourtant, C# était toujours en train de courir derrière Java. Java avait déjà publié des versions qui incluaient des génériques et des itérateurs. Mais cela allait bientôt changer quand les deux langages poursuivraient des chemins différents.

C# version 3.0

C# version 3.0 est apparu fin 2007, en même temps que Visual Studio 2008, même si l’éventail complet des fonctionnalités du langage n’a réellement voir le jour qu’avec le .NET Framework version 3.5. Cette version a insufflé un changement majeur dans l’évolution de C#. Elle a imposé C# en tant que langage de programmation vraiment formidable. Examinons certaines fonctionnalités importantes dans cette version :

Rétrospectivement, nombre de ces fonctionnalités semblent à la fois inéluctables et inséparables. Elles s’assemblent de façon stratégique. On pense que la fonctionnalité killer de la version C# était l’expression de requête, également appelée Language-Integrated Query (LINQ).

Un point de vue plus nuancé s’intéresse aux arborescences d’expressions, aux expressions lambda et aux types anonymes sur lesquels se construit LINQ. Mais, dans les deux cas, C# 3.0 présentait un concept révolutionnaire. C# 3.0 jetait les bases qui allaient permettre à C# de devenir un langage fonctionnel/orienté objet hybride.

Plus précisément, il devint alors possible d’écrire des requêtes déclaratives de style SQL pour effectuer des opérations sur des collections, entre autres choses. Au lieu d’écrire une boucle for pour calculer la moyenne d’une liste d’entiers, vous pouviez alors simplement utiliser list.Average(). La combinaison des expressions de requête et des méthodes d’extension a permis à de telles listes d’entiers de paraître beaucoup plus intelligentes.

Il a fallu du temps aux utilisateurs pour comprendre et intégrer ce concept, mais ils y sont progressivement parvenus. Et aujourd’hui, bien des années plus tard, le code est beaucoup plus concis, simple et fonctionnel.

C# version 4.0

C# version 4.0, publiée avec Visual Studio 2010, aurait eu du mal à atteindre le statut révolutionnaire de la version 3.0. Avec la version 3.0, le langage C# est bel et bien sorti de l’ombre de Java pour être propulsé sur le devant de la scène. Il allait même rapidement devenir élégant.

La version suivante introduisit de nouvelles fonctionnalités intéressantes :

Les types d’interopérabilité incorporés ont facilité la difficulté de déploiement de la création d’assemblys d’interopérabilité COM pour votre application. La covariance et la contravariance génériques vous donnent plus de contrôle sur l’utilisation des génériques, mais elles sont un peu académiques et probablement plus appréciées des auteurs de frameworks et de bibliothèques. Les paramètres nommés et facultatifs vous permettent d’éliminer les nombreuses surcharges de méthode et s’avèrent plus pratiques. Mais aucune de ces fonctionnalités ne représente un vrai changement de paradigme.

La fonctionnalité majeure était plutôt l’introduction du mot clé dynamic. Le mot clé dynamic introduisit dans C# version 4.0 la possibilité de remplacer le compilateur lors de la saisie au moment de la compilation. En utilisant le mot clé dynamic, vous pouvez créer des constructions semblables aux langages dynamiquement typés comme JavaScript. Vous pouvez créer un dynamic x = "a string", puis y ajouter six, et ainsi laisser le runtime se débrouiller avec ce qui doit se produire par la suite.

La liaison dynamique offre la possibilité de commettre des erreurs, mais également de contrôler davantage le langage.

C# version 5.0

C# version 5.0, publiée avec Visual Studio 2012, était une version ciblée du langage. Presque tous les efforts déployés pour cette version portaient sur un autre concept révolutionnaire du langage : le modèle async et await pour la programmation asynchrone. Voici la liste des principales fonctionnalités :

Voir aussi

L’attribut d’informations de l’appelant vous permet de récupérer facilement des informations sur le contexte d’exécution sans avoir recours à une multitude de code de réflexion réutilisable. Nombre de ses usages ont trait aux diagnostics et aux tâches de journalisation.

Mais async et await sont les véritables vedettes de cette version. Quand ces fonctionnalités sont apparues en 2012, C# a encore modifié la donne en intégrant l’asynchronie en tant que participant de premier ordre dans le langage. Si vous avez déjà eu affaire à de longues opérations et à l’implémentation de rappels, vous avez probablement adoré cette fonctionnalité de langage.

C# version 6.0

Avec les versions 3.0 et 5.0, C# avait ajouté d’importantes nouvelles fonctionnalités à un langage orienté objet. Avec la version 6.0, publiée avec Visual Studio 2015, elle ne serait plus une fonctionnalité tueuse dominante et publierait à la place de nombreuses fonctionnalités plus petites qui rendaient la programmation C# plus productive. En voici quelques-unes :

Quelques autres nouvelles fonctions :

  • Initialiseurs d’index
  • Await dans des blocs catch/finally
  • Valeurs par défaut pour les propriétés d’accesseur Get

Chacune de ces fonctionnalités est intéressante individuellement. Mais si vous les examinez dans leur ensemble, un modèle intéressant se dégage. Dans cette version, C# a éliminé le texte réutilisable du langage pour rendre le code plus laconique et plus lisible. Ainsi, pour les amateurs de code propre et simple, cette version du langage était une énorme victoire.

Une autre nouveauté a été proposée avec cette version, même s’il ne s’agit pas d’une fonctionnalité de langage traditionnelle à proprement dit. Le compilateur Roslyn a été publié en tant que service. Le compilateur C# est à présent écrit en C# et vous pouvez l’utiliser dans le cadre de vos efforts de programmation.

C# version 7.0

La version 7.0 de C# a été publiée avec Visual Studio 2017. Cette version propose des évolutions intéressantes dans l’esprit de C# 6.0, mais sans le compilateur en tant que service. Voici quelques-unes des nouvelles fonctionnalités :

Autres fonctionnalités disponibles :

Toutes ces fonctionnalités offrent de nouvelles capacités appréciables aux développeurs ainsi que la possibilité d’écrire du code encore plus propre. Il s’agit notamment de condenser la déclaration des variables à utiliser avec le mot clé out et en autorisant plusieurs valeurs de retour par le biais d’un tuple.

Par ailleurs, les utilisations de C# sont de plus en plus larges. .NET Core cible à présent n’importe quel système d’exploitation et garde les yeux rivés sur le cloud et la portabilité. Ces nouvelles fonctions occupent sans aucun doute les pensées des concepteurs du langage, en plus des fonctionnalités à venir.

C# version 7.1

C# a commencé à publier des versions ponctuelles avec C# 7.1. Cette version a ajouté l’élément de configuration de sélection de version de langue , trois nouvelles fonctionnalités de langage et un nouveau comportement du compilateur.

Les nouvelles fonctionnalités de langage de cette version sont :

  • asyncMain Méthode
    • Le point d’entrée pour une application peut avoir le modificateur async.
  • default expressions littérales
    • Vous pouvez utiliser des expressions littérales default dans les expressions de valeur par défaut quand le type cible peut être inféré.
  • Noms des éléments de tuple inférés
    • Les noms des éléments de tuple peuvent être inférés dans de nombreux cas à partir de l’initialisation du tuple.
  • Critères spéciaux sur les paramètres de type générique
    • Il est possible d’utiliser des expressions de critères spéciaux sur les variables dont le type est un paramètre de type générique.

Enfin, le compilateur a deux options -refout et -refonly qui contrôlent la génération d’assembly de référence

C# version 7.2

C# 7.2 a ajouté plusieurs petites fonctionnalités de langage :

  • Initialiseurs sur stackalloc les tableaux.
  • Utilisez fixed des instructions avec n’importe quel type qui prend en charge un modèle.
  • Accéder aux champs fixes sans épinglage.
  • Réaffecter ref des variables locales.
  • Déclarez readonly struct des types pour indiquer qu’un struct est immuable et doit être passé en tant que in paramètre à ses méthodes membres.
  • Ajoutez le in modificateur sur les paramètres pour spécifier qu’un argument est passé par référence, mais pas modifié par la méthode appelée.
  • Utilisez le ref readonly modificateur sur les retours de méthode pour indiquer qu’une méthode retourne sa valeur par référence, mais n’autorise pas les écritures dans cet objet.
  • Déclarez ref struct des types pour indiquer qu’un type struct accède directement à la mémoire managée et doit toujours être alloué par pile.
  • Utilisez des contraintes génériques supplémentaires.
  • Arguments nommés non placés en position de fin
    • Les arguments nommés peuvent être suivis par des arguments de position.
  • Traits de soulignement de début dans les littéraux numériques
    • Les littéraux numériques peuvent maintenant comporter des traits de soulignement de début avant tout chiffre affiché.
  • private protected modificateur d’accès
    • Le modificateur d’accès private protected active l’accès pour les classes dérivées dans le même assembly.
  • Expressions ref conditionnelles
    • Le résultat d’une expression conditionnelle (?:) peut maintenant être une référence.

C# version 7.3

Il existe deux thèmes principaux pour la version C# 7.3. Un thème fournit des fonctionnalités permettant au code sécurisé d’être aussi performant que le code non sécurisé. Le second thème fournit des améliorations incrémentielles aux fonctionnalités existantes. De nouvelles options de compilateur ont également été ajoutées dans cette version.

Les nouvelles fonctionnalités suivantes prennent en charge le thème de meilleures performances pour le code sécurisé :

  • Vous pouvez accéder à des champs fixes sans épinglage.
  • Vous pouvez réaffecter des variables locales ref.
  • Vous pouvez utiliser des initialiseurs sur les tableaux stackalloc.
  • Vous pouvez utiliser des instructions fixed avec tout type prenant en charge un modèle.
  • Vous pouvez utiliser des contraintes plus génériques.

Les améliorations suivantes ont été apportées aux fonctionnalités existantes :

  • Vous pouvez tester == et != avec des types de tuple.
  • Vous pouvez utiliser des variables d’expression dans d’autres emplacements.
  • Vous pouvez joindre des attributs à un champ de stockage de propriétés implémentées automatiquement.
  • La résolution de la méthode lorsque des arguments diffèrent de in a été améliorée.
  • La résolution de la surcharge comporte maintenant moins de cas ambigus.

Les nouvelles options du compilateur sont les suivantes :

  • -publicsign pour activer la signature d’assemblys Open Source Software (OSS).
  • -pathmap pour fournir un mappage des répertoires sources.

C# version 8.0

C# 8.0 est la première version C# majeure qui cible spécifiquement .NET Core. Certaines fonctionnalités s’appuient sur de nouvelles fonctionnalités CLR, d’autres sur des types de bibliothèques ajoutés uniquement dans .NET Core. C# 8.0 ajoute les fonctionnalités et améliorations suivantes au langage C# :

Les membres d’interface par défaut nécessitent des améliorations dans le CLR. Ces fonctionnalités ont été ajoutées dans le CLR pour .NET Core 3.0. Les plages et les index, ainsi que les flux asynchrones nécessitent de nouveaux types dans les bibliothèques .NET Core 3.0. Les types de référence pouvant être nullables, bien qu’implémentés dans le compilateur, sont beaucoup plus utiles lorsque les bibliothèques sont annotées pour fournir des informations sémantiques concernant l’état null des arguments et des valeurs de retour. Ces annotations sont ajoutées dans les bibliothèques .NET Core.

C# version 9

C# 9 a été publié avec .NET 5. Il s’agit de la version de langage par défaut pour tout assembly qui cible la version .NET 5. Il contient les fonctionnalités nouvelles et améliorées suivantes :

C# 9 poursuit trois des thèmes des versions précédentes : la suppression de la cérémonie, la séparation des données des algorithmes et la fourniture de modèles supplémentaires dans plus d’endroits.

Les instructions de niveau supérieur signifient que votre programme principal est plus simple à lire. Il y a moins besoin de cérémonie : un espace de noms, une Program classe et static void Main() sont tous inutiles.

Introduction de records fournir une syntaxe concise pour les types de référence qui suivent la sémantique des valeurs pour l’égalité. Vous allez utiliser ces types pour définir des conteneurs de données qui définissent généralement un comportement minimal. Les setters init uniquement fournissent la possibilité de mutation non destructrice (with expressions) dans les enregistrements. C# 9 ajoute également des types de retour covariants afin que les enregistrements dérivés puissent remplacer les méthodes virtuelles et renvoyer un type dérivé du type de retour de la méthode de base.

Les fonctionnalités de correspondance de modèles ont été développées de plusieurs manières. Les types numériques prennent désormais en charge les modèles de plage. Les modèles peuvent être combinés à l’aide de andmodèles , oret not . Des parenthèses peuvent être ajoutées pour clarifier des modèles plus complexes.

Un autre ensemble de fonctionnalités prend en charge le calcul hautes performances en C# :

  • Les nint types et nuint modélisent les types entiers de taille native sur le processeur cible.
  • Les pointeurs de fonction fournissent des fonctionnalités de type délégué tout en évitant les allocations nécessaires pour créer un objet délégué.
  • Vous localsinit pouvez omettre l’instruction pour enregistrer les instructions.

Un autre ensemble d’améliorations prend en charge les scénarios où les générateurs de code ajoutent des fonctionnalités :

C# 9 ajoute de nombreuses autres petites fonctionnalités qui améliorent la productivité des développeurs, à la fois l’écriture et la lecture du code :

  • Expressions de type new cible
  • static fonctions anonymes
  • Expressions conditionnelles de type cible
  • Prise en charge des GetEnumerator() extensions pour foreach les boucles
  • Les expressions lambda peuvent déclarer des paramètres d’abandon
  • Les attributs peuvent être appliqués aux fonctions locales

La version C# 9 poursuit le travail pour conserver C# un langage de programmation moderne à usage général. Les fonctionnalités continuent de prendre en charge les charges de travail et les types d’applications modernes.

C# version 10

C# 10 ajoute les fonctionnalités et améliorations suivantes au langage C# :

Des fonctionnalités supplémentaires sont disponibles en mode préversion . Nous vous encourageons à essayer ces fonctionnalités et à fournir des commentaires à leur sujet. Ils peuvent changer avant leur publication finale. Pour utiliser ces fonctionnalités, vous devez définir <LangVersion> sur Preview dans votre projet :

C# 10 poursuit le travail sur les thèmes de suppression de cérémonie, de séparation des données des algorithmes et d’amélioration des performances pour le runtime .NET.

La plupart des fonctionnalités signifient que vous taperez moins de code pour exprimer les mêmes concepts. Les structs d’enregistrement synthétisent un grand nombre des méthodes utilisées par les classes d’enregistrement . Les structs et les types anonymes prennent en charge les expressions. Les directives d’utilisation globales et les déclarations d’espace de noms délimitées aux fichiers signifient que vous exprimez plus clairement les dépendances et l’organisation de l’espace de noms. Les améliorations apportées à lambda facilitent la déclaration des expressions lambda là où elles sont utilisées. De nouveaux modèles de propriété et des améliorations de la déconstruction créent du code plus concis.

Les nouveaux gestionnaires de chaînes interpolées et AsyncMethodBuilder le nouveau comportement peuvent améliorer les performances. Ces fonctionnalités de langage ont été exploitées dans le runtime .NET pour améliorer les performances de .NET 6.

C# 10 marque également une évolution vers la cadence annuelle des versions .NET. Étant donné que toutes les fonctionnalités ne peuvent pas être terminées dans un délai annuel, vous pouvez essayer quelques fonctionnalités « en préversion » dans C# 10. Les attributs génériques et lesmembres abstraits statiques dans les interfaces peuvent être utilisés, mais il s’agit de fonctionnalités en préversion qui peuvent changer avant leur version finale.

Articleinitialement publié sur le blog NDepend, avec l’aimable autorisation d’Erik Dietrich et de Patrick Smacchia.