Microsoft a annoncé le mois dernier .NET 7 Preview 6, la version du framework pour la création des applications. Elle améliore les convertisseurs de type, personnalise des contrats JSON. « .NET 7 s'appuie sur la base établie par .NET 6, qui comprend un ensemble unifié de bibliothèques de base, de runtime et de SDK, une expérience de développement simplifiée et une productivité accrue des développeurs. Les principaux domaines d'intérêt de .NET 7 comprennent une meilleure prise en en charge des scénarios cloud native, des outils facilitant la mise à niveau des projets existants et la simplification de l'expérience du développeur en facilitant le travail avec les conteneurs », a écrit Jeremy Likness de l'équipe .NET à propos de cette version. En gros, .NET 7 vise à faciliter le développement d'applications cloud natives et la conteneurisation.
La boîte à outils de la communauté .NET est une collection d'aides et d'API qui fonctionnent pour tous les développeurs .NET et qui sont indépendants de toute plate-forme d'interface utilisateur spécifique. La boîte à outils est maintenue et publiée par Microsoft, et fait partie de la Fondation .NET. Elle est également utilisée par plusieurs projets internes et applications en boîte, comme le Microsoft Store. À partir de la nouvelle version 8.0.0, le projet se trouve désormais dans le dépôt CommunityToolkit/dotnet sur GitHub, qui comprend toutes les bibliothèques faisant partie de la boîte à outils.
Toutes les API disponibles ne dépendent d'aucun runtime ou framework spécifique et peuvent donc être utilisées par tous les développeurs .NET. Ces bibliothèques sont multi-cibles, de .NET Standard 2.0 à .NET 6, ce qui leur permet de prendre en charge le plus grand nombre de plateformes possible et d'être optimisées pour obtenir les meilleures performances lorsqu'elles sont utilisées sur des moteurs d'exécution plus récents.
Comme pour chaque version du Community Toolkit, toutes les modifications ont été influencées par les commentaires reçus à la fois par les équipes de Microsoft qui utilisent le Toolkit et par les autres développeurs de la communauté. Les bibliothèques du .NET Community Toolkit sont les suivantes :
- CommunityToolkit.Common ;
- CommunityToolkit.Mvvm (alias "Microsoft MVVM Toolkit") ;
- CommunityToolkit.Diagnostics ;
- CommunityToolkit.HighPerformance.
Vous vous demandez peut-être pourquoi la première version du .NET Community Toolkit est la version 8.0.0. Bonne question ! La raison en est que toutes les bibliothèques du .NET Community Toolkit faisaient à l'origine partie du Windows Community Toolkit, qui est une collection d'aides, d'extensions et de contrôles personnalisés qui simplifient et démontrent les tâches courantes des développeurs créant des applications UWP et .NET pour Windows 10 et Windows 11.
Au fil du temps, le nombre d'API ciblant uniquement .NET et ne comportant aucune dépendance spécifique à Windows a augmenté, et Microsoft a décidé de les séparer dans un projet distinct afin qu'elles puissent évoluer indépendamment et être plus faciles à trouver pour les développeurs .NET qui ne développent pas sous Windows. C'est ainsi qu'est né le .NET Community Toolkit. Cela a également permis de mieux organiser la documentation, qui comporte désormais des sections distinctes pour chaque boîte à outils spécifique à une plateforme.
Étant donné que la dernière version du Windows Community Toolkit avant de se ramifier était 7.1.x, Microsoft a décidé de suivre la sémantique de ce numéro de version pour rendre la transition plus facile à comprendre pour les utilisateurs, et c'est pourquoi la première version du .NET Community Toolkit est 8.0.0. À l'avenir, il sera versionné séparément du Windows Community Toolkit, car chaque projet aura sa propre feuille de route et son propre calendrier de publication.
Ceci étant éclairci, plongeons maintenant dans toutes les nouvelles fonctionnalités de cette nouvelle version majeure des bibliothèques du .NET Community Toolkit !
MVVM Toolkit
Comme annoncé précédemment dans la version 7.0, l'un des principaux composants du .NET Community Toolkit est le MVVM Toolkit : une bibliothèque MVVM moderne, rapide, agnostique en termes de plateforme et modulaire. Il s'agit de la même bibliothèque MVVM que celle utilisée par le Microsoft Store, l'application Photos, etc.
MVVM Toolkit s'inspire de MvvmLight, et est également son remplaçant officiel maintenant que la bibliothèque a été dépréciée. Microsoft a également collaboré avec Laurent Bugnion lors du développement de la boîte à outils MVVM, et il a approuvé la boîte à outils MVVM comme la voie à suivre pour les utilisateurs actuels de MvvmLight. Laurent Bugnion travaille en tant que Senior Cloud Developer Advocate pour Microsoft après avoir travaillé pendant près de 10 ans pour IdentityMine et Valorem.
La boîte à outils MVVM repose sur quelques principes clés :
- Plateforme agnostique : cela signifie qu'il ne dépend d'aucun framework d'interface utilisateur spécifique. Il peut être utilisé pour partager du code entre UWP, WinUI 3, MAUI, WPF, Avalonia, Uno, et bien plus ;
- Agnostique en matière de runtime : la bibliothèque est multicible et prend en charge jusqu'à .NET Standard 2.0, ce qui signifie que vous pouvez bénéficier d'améliorations des performances lors de l'exécution sur des runtimes modernes (par exemple .NET 6), tout en continuant à l'utiliser même sur .NET Framework ;
- Simplicité de prise en main et d'utilisation : il n'y a pas d'exigences strictes concernant la structure de l'application ou les modèles de codage à utiliser. Vous pouvez utiliser la bibliothèque en fonction de votre propre architecture et de votre style ;
- À la carte : tous les composants sont indépendants et peuvent également être utilisés séparément. Il n'y a pas d'approche "tout compris" à laquelle vous êtes contraint : si vous ne souhaitez utiliser qu'un seul type de la bibliothèque, vous pouvez le faire sans problème, puis utiliser progressivement d'autres fonctionnalités selon vos besoins ;
- Implémentation de référence : toutes les API disponibles sont conçues pour être légères et performantes, en fournissant des "implémentations de référence" pour les interfaces qui sont incluses dans la bibliothèque de classes de base .NET, mais ne disposent pas de types concrets pour les utiliser directement. Par exemple, vous pourrez trouver une « mise en œuvre de référence » pour des interfaces telles que INotifyPropertyChanged ou ICommand.
La plus grande nouveauté de la version 8.0.0 de la boîte à outils MVVM sont les nouveaux générateurs de sources MVVM, qui sont destinés à réduire considérablement le code passe-partout nécessaire pour configurer une application utilisant MVVM. Par rapport aux générateurs de prévisualisation que Microsoft a livré dans la version 7.1.0, ils ont également été complètement réécrits pour être des générateurs incrémentiels, ce qui signifie qu'ils fonctionneront beaucoup plus rapidement qu'avant et qu'ils aideront à maintenir l'EDI rapide et réactif, même lorsque vous travaillez sur des projets à grande échelle.
La création de commandes peut être assez répétitive, avec la nécessité de configurer une propriété pour chaque méthode que nous voulons exposer de manière abstraite aux différents composants de l'interface utilisateur de nos applications qui sont censés les invoquer (comme les boutons). C'est là que le nouvel attribut [RelayCommand] entre en jeu : il permettra à la boîte à outils MVVM de générer automatiquement des commandes (en utilisant les types RelayCommand inclus dans la bibliothèque) avec la bonne signature, en fonction de la méthode annotée.
À titre de comparaison, voici comment on procède habituellement pour mettre en place une commande :
Code : | Sélectionner tout |
1 2 3 4 5 6 7 8 | private IRelayCommand<User> greetUserCommand; public IRelayCommand<User> GreetUserCommand => greetUserCommand ??= new RelayCommand<User>(GreetUser); private void GreetUser(User user) { Console.WriteLine($"Hello {user.Name}!"); } |
Cela peut maintenant être simplifié à ceci :
Code : | Sélectionner tout |
1 2 3 4 5 | [RelayCommand] private void GreetUser(User user) { Console.WriteLine($"Hello {user.Name}!"); } |
Le générateur de sources se chargera de créer la bonne propriété GreetUserCommand en fonction de la méthode annotée. En outre, une méthode CanExecute peut également être spécifiée, et il est également possible de contrôler le niveau de concurrence pour les commandes asynchrones. Il existe également d'autres options permettant d'affiner le comportement des commandes générées.
Propriétés observables
L'écriture de propriétés observables peut être extrêmement verbeuse, surtout lorsqu'il faut également ajouter une logique supplémentaire pour gérer les propriétés dépendantes qui sont notifiées. Tout cela peut être grandement simplifié en utilisant les nouveaux attributs du MVVM Toolkit et en laissant le générateur de sources créer des propriétés observables en coulisse.
Les nouveaux attributs sont [ObservableProperty], [NotifyPropertyChangedFor] et [NotifyCanExecuteChangedFor], [NotifyDataErrorInfo] et [NotifyPropertyChangedRecipients]. Passons rapidement en revue ce que tous ces nouveaux attributs peuvent faire.
Considérons un scénario dans lequel il existe deux propriétés observables, une propriété dépendante et la commande définie ci-dessus, et dans lequel la propriété dépendante et la commande doivent être notifiées lorsque l'une des deux propriétés observables change. Autrement dit, lorsque FirstName ou LastName changent, FullName est également notifié, ainsi que la commande GreetUserCommand.
C'est ainsi que cela aurait été fait dans le passé :
Code : | Sélectionner tout |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 | private string? firstName; public string? FirstName { get => firstName; set { if (SetProperty(ref firstName, value)) { OnPropertyChanged(nameof(FullName)); GreetUserCommand.NotifyCanExecuteChanged(); } } } private string? lastName; public string? LastName { get => lastName; set { if (SetProperty(ref lastName, value)) { OnPropertyChanged(nameof(FullName)); GreetUserCommand.NotifyCanExecuteChanged(); } } } public string? FullName => $"{FirstName} {LastName}"; |
Tout cela peut maintenant être réécrit comme suit :
Code : | Sélectionner tout |
1 2 3 4 5 6 7 8 9 10 11 | [ObservableProperty] [NotifyPropertyChangedFor(nameof(FullName))] [NotifyCanExecuteChangedFor(nameof(GreetUserCommand))] private string? firstName; [ObservableProperty] [NotifyPropertyChangedFor(nameof(FullName))] [NotifyCanExecuteChangedFor(nameof(GreetUserCommand))] private string? lastName; public string? FullName => $"{FirstName} {LastName}"; |
La boîte à outils MVVM se chargera de la génération du code pour ces propriétés, y compris l'insertion de toute la logique permettant de déclencher les événements de changement de propriété spécifiés ou d'exécuter les événements de changement.
Mais attendez, il y a plus ! Lorsque vous utilisez [ObservableProperty] pour générer des propriétés observables, la boîte à outils MVVM génère également deux méthodes partielles sans implémentation : On<PROPERTY_NAME>Changing et On<PROPERTY_NAME>Changed. Ces méthodes peuvent être utilisées pour injecter une logique supplémentaire lorsqu'une propriété est modifiée, sans avoir à recourir à une propriété manuelle. Notons qu'étant donné que ces deux méthodes sont partielles, à retour nul et sans définition, le compilateur C# les supprimera complètement si elles ne sont pas implémentées, ce qui signifie que lorsqu'elles ne sont pas utilisées, elles disparaissent tout simplement et n'ajoutent aucune surcharge à l'application.
Voici un exemple de la façon dont ils peuvent être utilisés :
Code : | Sélectionner tout |
1 2 3 4 5 6 7 8 9 10 11 12 | [ObservableProperty] private string name; partial void OnNameChanging(string name) { Console.WriteLine($"The name is about to change to {name}!"); } partial void OnNameChanged(string name) { Console.WriteLine($"The name just changed to {name}!"); } |
Bien entendu, vous êtes également libre de n'implémenter qu'une seule de ces deux méthodes, ou aucune. À partir de l'extrait ci-dessus, le générateur de sources produira un code analogue à celui-ci :
Code : | Sélectionner tout |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 | public string Name { get => name; set { if (!EqualityComparer<string>.Default.Equals(name, value)) { OnNameChanging(value); OnPropertyChanging(); name = value; OnNameChanged(); OnPropertyChanged(); } } } partial void OnNameChanging(string name); partial void OnNameChanged(string name); |
L'attribut [ObservableProperty] prend également en charge la validation : si l'un des champs représentant une propriété possède un ou plusieurs attributs héritant de ValidationAttribute, ceux-ci seront automatiquement copiés dans les propriétés générées. Cette approche est donc entièrement prise en charge lorsque vous utilisez ObservableValidator pour créer des formulaires validables. Si vous souhaitez que la propriété soit validée chaque fois que sa valeur est définie, vous pouvez également ajouter [NotifyDataErrorInfo] pour que le code de validation soit également généré dans le paramètre de la propriété.
D'autres fonctionnalités sont disponibles pour [ObservableProperty] et, comme pour les commandes.
Prise en charge de l'annulation pour les commandes
Une nouvelle propriété a été ajoutée à l'attribut [RelayCommand], qui peut être utilisée pour demander au générateur de source de générer une commande d'annulation en plus de la commande originale. Cette commande d'annulation peut être utilisée pour annuler l'exécution d'une commande asynchrone.
Cela montre également comment [RelayCommand] peut s'adapter automatiquement aux méthodes asynchrones et aux méthodes qui acceptent également des paramètres, et créer des implémentations de commandes asynchrones en coulisse. Cela permet également de mettre en place des fonctionnalités supplémentaires, comme des liaisons faciles à configurer pour afficher des indicateurs de progression, etc.
Voici un exemple de la façon dont ils peuvent être utilisés :
Code : | Sélectionner tout |
1 2 3 4 5 | [RelayCommand(IncludeCancelCommand = true)] private async Task DoWorkAsync(CancellationToken token) { // Do some long running work with cancellation support } |
À partir de ce petit extrait, le générateur produira le code suivant :
Code : | Sélectionner tout |
1 2 3 4 5 6 7 | private AsyncRelayCommand? doWorkCommand; public IAsyncRelayCommand DoWorkCommand => doWorkCommand ??= new AsyncRelayCommand(DoWorkAsync); ICommand? doWorkCancelCommand; public ICommand DoWorkCancelCommand => doWorkCancelCommand ??= IAsyncRelayCommandExtensions.CreateCancelCommand(UpdateSomethingCommand); |
Ce code généré, combiné à la logique de l'API IAsyncRelayCommandExtensions.CreateCancelCommand, permet de n'avoir besoin que d'une seule ligne de code pour qu'une commande soit générée, notifiant l'interface utilisateur dès que le travail a commencé ou est en cours d'exécution, avec un contrôle automatique de la concurrence (la commande est désactivée par défaut lorsqu'elle est déjà en cours d'exécution). La commande d'annulation séparée sera notifiée chaque fois que la commande primaire commencera ou finira de s'exécuter, et lorsqu'elle sera exécutée, elle signalera l'annulation au jeton passé à la méthode enveloppée par la commande primaire. Tout ceci est complètement abstrait et facilement accessible avec un seul attribut.
Prise en charge des changements de diffusion pour les propriétés générées
Microsoft a également ajouté un nouvel attribut [NotifyPropertyChangedRecipients] qui peut être utilisé sur une propriété observable générée à partir d'un type qui hérite de ObservableRecipient (ou qui est annoté avec [ObservableRecipient]). Son utilisation génèrera un appel à la méthode Broadcast, afin d'envoyer un message à tous les autres composants abonnés au sujet du changement de propriété qui vient de se produire. Cela peut être utile dans les scénarios où un changement de propriété d'un modèle de vue doit également être notifié à d'autres composants de l'application (Supposons qu'il y ait une propriété booléenne IsLoggedIn qui se met à jour lorsqu'un utilisateur se connecte ; cela peut notifier et déclencher le rafraîchissement de certains autres composants de l'application avec le message diffusé).
Il peut être utilisé comme suit :
Code : | Sélectionner tout |
1 2 3 | [ObservableProperty] [NotifyPropertyChangedRecipients] private string name; |
Et cela produira un code analogue à celui-ci :
Code : | Sélectionner tout |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 | public string Name { get => name; set { if (!EqualityComparer<string>.Default.Equals(name, value)) { OnNameChanging(value); OnPropertyChanging(); string oldValue = name; name = value; Broadcast(oldValue, value, nameof(Name)); OnNameChanged(); OnPropertyChanged(); } } } |
Il s'agit d'une autre fonctionnalité permettant d'augmenter les propriétés générées et de garantir qu'elles peuvent être utilisées dans presque tous les scénarios, sans être obligé de se rabattre sur des propriétés manuelles.
Composition du ViewModel
Le C# ne dispose pas de l'héritage multiple, ce qui peut parfois poser problème. Que faire si un modèle de vue doit hériter d'un type spécifique, mais que vous souhaitez également injecter la prise en charge de INotifyPropertyChanged ou qu'il hérite également de ObservableRecipient pour avoir accès à ses API ?
Le MVVM Toolkit permet désormais de contourner ce problème en introduisant des attributs pour la génération de code qui permettent d'injecter la logique de ces types dans des classes arbitraires. Il s'agit de [INotifyPropertyChanged], [ObservableObject] et [ObservableRecipient]. En les ajoutant à une classe, le générateur de sources MVVM Toolkit inclura toute la logique de ce type dans cette classe, comme si cette classe avait également hérité de ce type. Par exemple :
Code : | Sélectionner tout |
1 2 3 4 | [INotifyPropertyChanged] partial class MyObservableViewModel : DatabaseItem { } |
Il est toujours recommandé d'hériter des types de base tels que ObservableObject chaque fois que cela est nécessaire, car cela peut également aider à réduire la taille binaire, mais avoir la possibilité d'injecter du code de cette façon lorsque cela est nécessaire peut aider à contourner les limitations de C# dans les cas où le changement du type de base d'un viewmodel est tout simplement impossible, comme dans l'exemple ci-dessus.
Amélioration des API de messagerie
Une autre fonctionnalité couramment utilisée dans le MVVM Toolkit est l'interface IMessenger, qui est un contrat pour les types qui peuvent être utilisés pour échanger des messages entre différents objets. Cela peut être utile pour découpler différents modules d'une application sans avoir à conserver des références fortes aux types référencés. Il est également possible d'envoyer des messages à des canaux spécifiques, identifiés de manière unique par un jeton, et d'avoir différents messagers dans différentes sections d'une application.
Le MVVM Toolkit fournit deux implémentations de cette interface :
- WeakReferenceMessenger : qui n'enracine pas les destinataires et les autorise à être collectés. Ceci est mis en œuvre par le biais de handles dépendants, qui sont un type spécial de références GC permettant à ce messager de s'assurer qu'il autorise toujours les destinataires enregistrés à être collectés, même si un gestionnaire enregistré les renvoie, mais qu'il n'existe pas d'autres références fortes à eux ;
- StrongReferenceMessenger : il s'agit d'une implémentation de messager qui enracine les destinataires enregistrés pour s'assurer qu'ils restent en vie même si le messager est le seul objet à les référencer.
Voici un petit exemple de la façon dont cette interface peut être utilisée :
Code : | Sélectionner tout |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 | // Declare a message public sealed record LoggedInUserChangedMessage(User user); // Register a recipient explicitly... messenger.Register<MyViewModel, LoggedInUserChangedMessage>(this, static (r, m) => { // Handle the message here, with r being the recipient and m being the // input message. Using the recipient passed as input makes it so that // the lambda expression doesn't capture "this", improving performance. }); // ...or have the viewmodel implement IRecipient<TMessage>... class MyViewModel : IRecipient<LoggedInUserChangedMessage> { public void Receive(LoggedInUserChangedMessage message) { // Handle the message here } } // ...and then register through the interface (other APIs are available too) messenger.Register<LoggedInuserChangedMessage>(this); // Send a message from some other module messenger.Send(new LoggedInUserChangedMessage(user)); |
Les implémentations des messagers dans cette nouvelle version du MVVM Toolkit ont été hautement optimisées dans .NET 6 grâce à la nouvelle API publique DependentHandle, qui permet aux types de messagers d'être encore plus rapides qu'auparavant et d'offrir une diffusion de messages totalement sans allocation. Voici quelques benchmarks montrant comment les messagers de la MVVM Toolkit se comportent par rapport à plusieurs autres types équivalents d'autres bibliothèques MVVM largement utilisées :
Chaque exécution du benchmark consiste à envoyer 4 messages différents 1000 fois, à 100 destinataires. Comme vous pouvez le constater, WeakReferenceMessenger et StrongReferenceMessenger sont tous deux de loin les plus rapides, et les seuls à ne pas allouer ne serait-ce qu'un seul octet lors de la diffusion des messages....
API de collecte remaniée
Cette nouvelle version du MVVM Toolkit déplace également tous les types de collections groupées observables du paquet CommunityToolkit.Common vers CommunityToolkit.Mvvm, tout en effectuant quelques changements majeurs pour améliorer la surface de l'API et la rendre utile dans davantage de scénarios. Ces API sont particulièrement utiles lorsqu'on travaille avec des éléments groupés (par exemple, pour afficher une liste de contacts), et elles comprennent maintenant des extensions qui facilitent grandement les opérations courantes telles que l'insertion d'un élément à la bonne position dans un groupe (en utilisant soit le comparateur par défaut, soit un comparateur en entrée, et en créant un nouveau groupe si nécessaire).
Annonce de l'application type de la boîte à outils MVVM
Pour accompagner la nouvelle version, Microsoft a également publié l'application type dans le Microsoft Store ! Elle comprend toute la documentation également disponible sur MS Docs, ainsi que des échantillons interactifs pour de nombreuses API disponibles. Il s'agit d'un accessoire de la MVVM Toolkit.
Amélioration des API de diagnostic
Le paquet CommunityToolkit.Diagnostics a également reçu quelques nouvelles améliorations, tirant parti des nouvelles fonctionnalités du gestionnaire de chaînes interpolées et de l'expression des arguments de l'appelant de C# 10. Plusieurs API de garde qui prenaient auparavant une chaîne de caractères acceptent désormais également un gestionnaire personnalisé, ce qui permet aux sites d'appel de sauter complètement l'étape d'interpolation si aucune exception n'est levée, et il n'est plus nécessaire d'indiquer manuellement le nom de l'argument.
Voici une comparaison rapide avant et après :
/
Code : | Sélectionner tout |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 | / Diagnostics 7.1 public static void SampleMethod(int[] array, int index, Span<int> span, string text) { Guard.IsNotNull(array, nameof(array)); Guard.HasSizeGreaterThanOrEqualTo(array, 10, nameof(array)); Guard.IsInRangeFor(index, array, nameof(index)); Guard.HasSizeLessThanOrEqualTo(array, span, nameof(span)); Guard.IsNotNullOrEmpty(text, nameof(text)); } // Diagnostics 8.0 public static void SampleMethod(int[] array, int index, Span<int> span, string text) { Guard.IsNotNull(array); Guard.HasSizeGreaterThanOrEqualTo(array, 10); Guard.IsInRangeFor(index, array); Guard.HasSizeLessThanOrEqualTo(array, span); Guard.IsNotNullOrEmpty(text); } |
Prise en charge de .NET 6
Cette nouvelle version du .NET Community Toolkit ajoute également la prise en charge de .NET 6 comme nouvelle cible dans toutes les bibliothèques disponibles. Cela apporte plusieurs améliorations lors de l'exécution sur le dernier runtime .NET :
La prise en charge du trimming est maintenant activée pour toutes les bibliothèques. Pour soutenir cela, tous les paquets ont également des annotations de découpage complet pour toutes les API, afin de s'assurer que tout est soit convivial pour le linker, soit affiche explicitement les avertissements corrects au moment de la compilation (par exemple, c'est le cas pour certaines API de validation dans le MVVM Toolkit, qui utilisent certaines API de la BCL qui nécessitent intrinsèquement une certaine réflexion pour fonctionner).
L'extension Count() du paquetage HighPerformance prend désormais également en charge nint et nuint. Plusieurs autres optimisations ont été introduites dans tous les paquets pour .NET 6. Bien entendu, toutes les bibliothèques continueront à être prises en charge jusqu'à .NET Standard 2.0, de sorte que vous pourrez continuer à les référencer dans des projets utilisant des frameworks cibles différents.
Et grâce au fonctionnement de la résolution des paquets NuGet, si vous créez une bibliothèque à l'aide de l'un de ces paquets et d'un framework cible inférieur (par exemple, .NET Standard 2.0) et qu'un utilisateur la référence à partir d'un projet ciblant une nouvelle version de .NET (par exemple, .NET 6), il obtiendra toujours automatiquement la version la plus optimisée des assemblages du .NET Community Toolkit qui est disponible pour lui.
Source : Microsoft
Et vous ?
Quel es votre avis sur le sujet ?
Voir aussi :
Microsoft annonce .NET 7 Preview 6, la version du framework pour la création des applications, améliore les convertisseurs de type, personnalise des contrats JSON
Microsoft annonce .NET 7 Preview 3, la version du framework pour la création des applications, apporte une amélioration du temps de démarrage avec la fonction Write-Xor-Execute activée de 10 à 15 %
Microsoft annonce .NET 7 Preview 4, la version du framework pour la création des applications, elle corrige les bogues et comprend des MAJ
Microsoft publie le premier aperçu de .NET 7 avec des optimisations continues du compilateur JIT, de nouvelles API et la prise en charge de plus de scénarios de rechargement à chaud