Considérations relatives à la version et la mise à jour pour les développeurs C#

La compatibilité est un objectif important quand de nouvelles fonctionnalités sont ajoutées au langage C#. Dans presque tous les cas, le code existant peut être recompilé avec une nouvelle version du compilateur sans problème. L’équipe du runtime .NET a également pour objectif de garantir la compatibilité des bibliothèques mises à jour. Dans presque tous les cas, lorsque votre application est lancée à partir d’un runtime mis à jour avec des bibliothèques mises à jour, le comportement reste exactement le même qu’avec les versions précédentes.

La version du langage utilisée pour compiler l’application correspond généralement au moniker de framework cible (TFM) du runtime référencé dans votre projet. Pour plus d’informations sur le changement de la version du langage par défaut, consultez l’article intitulé Configurer la version du langage. Ce comportement par défaut garantit une compatibilité maximale.

Quand des changements cassants sont introduits, ils sont classés de la façon suivante :

  • Changement cassant binaire : un changement cassant binaire entraîne un comportement différent, y compris potentiellement un plantage, dans votre application ou bibliothèque qui est lancée à partir d’un nouveau runtime. Vous devez recompiler votre application pour incorporer ces changements. Le binaire existant ne fonctionnera pas correctement.
  • Changement cassant source : un changement cassant source modifie la signification de votre code source. Vous devez modifier le code source avant de compiler votre application avec la dernière version du langage. Votre binaire existant s’exécutera correctement avec la version plus récente de l’hôte et du runtime. Notez que pour la syntaxe du langage, un changement cassant source est également un changement de comportement, comme défini dans les changements cassants de runtime.

Quand un changement cassant binaire impacte votre application, vous devez recompiler l’application, mais vous n’avez pas besoin de modifier le code source. Quand un changement cassant source impacte votre application, le binaire existant continue de s’exécuter correctement dans les environnements avec le runtime et les bibliothèques mis à jour. Toutefois, vous devez apporter les modifications sources à recompiler avec la nouvelle version du langage et du runtime. Si une modification est à la fois un changement cassant source et un changement cassant binaire, vous devez recompiler votre application avec la dernière version et effectuer les mises à jour sources.

En raison de l’objectif recherché d’éviter les changements cassants par l’équipe du langage C# et l’équipe du runtime, la mise à jour de votre application consiste généralement à mettre à jour le TFM et à recompiler l’application. Toutefois, pour les bibliothèques qui sont distribuées publiquement, vous devez soigneusement évaluer votre stratégie de prise en charge des versions des TFM et des langages. Vous créez peut-être une nouvelle bibliothèque avec des fonctionnalités incluses dans la version la plus récente et avez besoin de vous assurer que les applications créées à l’aide de versions précédentes du compilateur peuvent l’utiliser. Ou vous mettez peut-être à niveau une bibliothèque existante et la plupart de vos utilisateurs ne disposent pas encore des versions mises à niveau.

Introduction de changements cassants dans vos bibliothèques

Lorsque vous adoptez de nouvelles fonctionnalités de langage dans l’API publique de votre bibliothèque, vous devez évaluer si l’adoption d’une fonctionnalité va introduire un changement cassant binaire ou source pour les utilisateurs de votre bibliothèque. Toutes les modifications apportées à votre implémentation interne qui n’apparaissent pas dans les interfaces public ou protected sont compatibles.

Notes

Si vous utilisez System.Runtime.CompilerServices.InternalsVisibleToAttribute pour permettre aux types de voir les membres internes, les membres internes risquent d’introduire des changements cassants.

En présence d’un changement cassant binaire, les utilisateurs doivent recompilent leur code afin d’utiliser la nouvelle version. Par exemple, examinez cette méthode publique :

public double CalculateSquare(double value) => value * value;

Si vous ajoutez le modificateur in à la méthode, il s’agit d’un changement cassant binaire :

public double CalculateSquare(in double value) => value * value;

Les utilisateurs doivent alors recompiler toute application utilisant la méthode CalculateSquare pour que la nouvelle bibliothèque fonctionne correctement.

Un changement cassant source oblige les utilisateurs à modifier leur code avant de le recompiler. Par exemple, examinez ce type :

public class Person
{
    public string FirstName { get; }
    public string LastName { get; }

    public Person(string firstName, string lastName) => (FirstName, LastName) = (firstName, lastName);

    // other details omitted
}

Dans une version plus récente, vous souhaitez tirer parti des membres synthétisés générés pour les types record. Vous apportez la modification suivante :

public record class Person(string FirstName, string LastName);

La modification précédente nécessite de modifier aussi tous les types dérivés de Person. Toutes ces déclarations doivent ajouter le modificateur record à leurs déclarations.

Impact des changements cassants

Lorsque vous introduisez un changement cassant binaire dans votre bibliothèque, vous forcez la recompilation de tous les projets qui utilisent cette bibliothèque. Toutefois, aucun code source dans ces projets n’a besoin d’être modifié. L’impact du changement cassant est donc relativement faible pour chaque projet.

Quand vous introduisez un changement cassant source dans votre bibliothèque, vous forcez tous les projets à apporter les modifications sources afin d’utiliser votre nouvelle bibliothèque. Si la modification à faire nécessite de nouvelles fonctionnalités de langage, vous forcez ces projets à effectuer une mise à niveau vers la même version de langage et le même TFM que vous utilisez actuellement. Vous avez accru la charge de travail de vos utilisateurs, et vous les avez éventuellement forcés à effectuer une mise à niveau.

L’impact réel de l’introduction d’un changement cassant dépend du nombre de projets qui dépendent de votre bibliothèque. Si votre bibliothèque est utilisée en interne par quelques applications seulement, vous pouvez traiter les changements cassants dans tous les projets impactés. En revanche, si votre bibliothèque est téléchargée publiquement, vous devez évaluer l’impact potentiel et envisager des alternatives :

  • Vous pouvez ajouter de nouvelles API en parallèle aux API existantes.
  • Vous pouvez envisager des builds parallèles pour différents TPM.
  • Vous pouvez envisager le multiciblage.