IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)

Vous êtes nouveau sur Developpez.com ? Créez votre compte ou connectez-vous afin de pouvoir participer !

Vous devez avoir un compte Developpez.com et être connecté pour pouvoir participer aux discussions.

Vous n'avez pas encore de compte Developpez.com ? Créez-en un en quelques instants, c'est entièrement gratuit !

Si vous disposez déjà d'un compte et qu'il est bien activé, connectez-vous à l'aide du formulaire ci-dessous.

Identifiez-vous
Identifiant
Mot de passe
Mot de passe oublié ?
Créer un compte

L'inscription est gratuite et ne vous prendra que quelques instants !

Je m'inscris !

C# 9.0 est en développement et Microsoft prévoit de nouvelles fonctionnalités comme les constructeurs principaux
Qui permettent de réduire les frais généraux de programmation

Le , par Bill Fassinou

67PARTAGES

5  0 
Microsoft a publié C# 8.0 en septembre dernier et a aussi entamé les travaux pour la version 9.0 du langage. Plusieurs propositions ont été faites parmi lesquelles l’on retrouve des fonctionnalités très intéressantes. La prochaine version de C# pourrait apporter les expressions switchs, les types records et un code de validation des paramètres nuls simplifié. Le jalon C# 9.0 sur GitHub recense toutes les fonctionnalités proposées par la communauté, mais n’annonce aucune date de sortie officielle pour la prochaine version de C#. Voici quelques-unes des propositions.

Validation nulle simplifiée

Cette nouvelle fonctionnalité permet de simplifier la validation des paramètres standard en utilisant une petite annotation sur les paramètres. En décorant la valeur d'un paramètre à une méthode avec une petite annotation, cela facilite la logique interne et l’on n’a plus besoin de clauses de validation/garde nulles. Cela a pour effet de réduire le code de validation passe-partout.

Constructeurs principaux

Selon la description de la fonctionnalité, les constructeurs principaux permettent de réduire les frais généraux de programmation en plaçant les arguments des constructeurs directement dans le champ d'application d'une classe. En gardant votre logique de construction minimale, vous éliminez le code superflu qui encourage l'écrémage des fichiers de code au lieu de faire un véritable examen du code. En ayant moins de code, vous rendez plus difficile la dissimulation de bogues et votre code est plus significatif.

En d’autres mots, vous n’avez plus besoin de déclarer explicitement un champ d'appui. Cela simplifie tous ces constructeurs, ces champs, ces getters/setters de propriété, etc. auxquels vous êtes si habitués.


Classes record

C’est un formulaire de déclaration simplifié pour une classe C# ainsi que les types de structures. Les records sont similaires aux constructeurs principaux cités en haut. Le but de cette proposition est de supprimer la nécessité d'écrire autant de code passe-partout lors de la création d'une nouvelle classe ou d’une structure. Ils fournissent un mécanisme de déclaration d'un type de données en décrivant les membres de l'agrégat ainsi que le code supplémentaire ou les écarts par rapport à l'habituel passe-partout, le cas échéant.

Unions discriminées via les classes Enum

Le terme d'union discriminée (union disjointe) est emprunté aux mathématiques. L'union discriminée est également largement utilisée dans les langages de programmation, et sert à additionner les types de données existants. Dans C# 9.0, il permet de définir des types pouvant contenir un nombre quelconque de types de données différents. Leur fonctionnalité est comparable à celle des unions C++ ou des variantes Visual Basic, avec l'avantage d'être plus sûres.
Les unions discriminées sont utiles pour les données hétérogènes ; les données qui peuvent avoir des cas individuels, avec des cas de validité et d'erreur ; les données dont le type varie d'une instance à l'autre. En outre, elle offre une alternative pour les petites hiérarchies d'objets.

CallerArgumentExpression

Cette fonctionnalité a pour but de permettre aux développeurs de capturer l'expression transmise à une méthode, de permettre de meilleurs messages d'erreur dans les API de diagnostic/test et de réduire le nombre de frappes.

Déclarations de haut niveau et déclarations des membres, englobant un dialecte de scripts dans le C#

Le compilateur C# comprend actuellement un dialecte du langage utilisé pour les scripts et à des fins interactives. L'utilisation du dialecte de script a été relativement mineure, mais l'usage s'intensifie. Le plan est basé sur la conviction que des extensions de C# pourraient être ajoutées au langage plutôt que d'avoir un dialecte de script séparé.

Le C# est un langage de programmation orienté objet appartenant à la famille C, et similaire à Java. Il prend également en charge la collecte des déchets et la programmation orientée composants, en utilisant des paquets de fonctionnalités autonomes et autodescriptives. La liste de toutes les propositions pour C# 9 est disponible sur la page GitHub du langage.

Source : C#

Et vous ?

Qu'en pensez-vous ?

Voir aussi

.NET Core 3.0 est disponible avec le support du développement d'applications Windows Desktop C# 8.0, ARM64, une prise en charge JSON intégrée rapide et de nombreuses autres améliorations

C# 8.x va introduire la fonctionnalité Records pour faciliter la création des classes POCO, selon Developers Anonymous

Microsoft livre un aperçu des nouveautés de C# 8.0 et envisage de commencer à livrer cette version dans les préversions de Visual Studio 2019

Une erreur dans cette actualité ? Signalez-nous-la !

Avatar de mermich
Membre expérimenté https://www.developpez.com
Le 25/05/2020 à 16:22
Dans le debat classe vs struct, il ya aussi les generiques :

Code : Sélectionner tout
public void Prout<T>(T t) where T : class
ce qui engrange des doublon si l'on doit a la fois gerer des classes et des structures...
Au final avec le temps je pousse mes collegues a ne pas utiliser les struct pour toutes ces raisons. Mais il reste ce soucis de mutabilite que l'on ne desire pas forcement.

Je me demande si ces data class fonctionnent correctement lors d'un post mvc, par exemple
2  0 
Avatar de mermich
Membre expérimenté https://www.developpez.com
Le 21/05/2020 à 21:15
Ca me fait penser pas mal q certaines fonctionnalites des koltin, je dis n'importe quoi ou c'est bien le cas ?
1  0 
Avatar de codec_abc
Membre confirmé https://www.developpez.com
Le 21/05/2020 à 23:58
Je connais pas Kotlin mais l'inspiration vient surement de F# qui à ce genre de features depuis longtemps. C'est la stratégie de Microsoft depuis longtemps. F# sert en quelque sorte de Labo et les features sont ensuite intégré dans C#.
1  0 
Avatar de StringBuilder
Expert éminent https://www.developpez.com
Le 22/05/2020 à 14:25
Bonjour,

Y'a un truc que j'ai pas bien compris avec le "record" (mot clé data).

Du coup, c'est quoi la différence entre un "struct" et un "class data", mise à part que le "class data" est readonly ?

Pourquoi ne pas avoir créé un "struct readonly" à la place du coup ?

Transformer une déclaration de type référence en type valeur, alors qu'une déclaration de type valeur existe déjà, je suis perplexe !
1  0 
Avatar de StringBuilder
Expert éminent https://www.developpez.com
Le 22/05/2020 à 21:13
Citation Envoyé par zero_divide  Voir le message
Moi qui structure mon code selon le "Domain-driven design (DDD)", c’est évidemment pour représenter un Value Object.

Justement, j'ai un peu du mal à comprendre…

A la base, une instance d'objet, c'est une référence.
Donc un objet valeur c'est à la base plus ou moins antonyme.

C#, depuis la version 1.0 a coupé la poire en deux, en proposant les structures, qui n'ont rien à voir avec les structures qu'on peut trouver dans d'autres langages : ce sont des objets à part entière (ils héritent d'ailleurs du type objetc) et supportent méthodes et constructeurs... La seule grosse différence avec une classe, c'est d'être justement un type valeur.

Code csharp : 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
33
34
35
36
37
38
39
40
41
42
using System; 
  
namespace StructOrObject 
{ 
    class Program 
    { 
        static void Main(string[] args) 
        { 
            MaStructure s1 = new MaStructure("Alfred", "E. Neuman"); 
            Console.WriteLine(s1.FullName); 
            Console.WriteLine(s1.NbNotEmptyChars()); 
  
            MaStructure s2 = new MaStructure() { FullName = "Alfred E. Neuman" }; 
            Console.WriteLine(s2.FullName); 
            Console.WriteLine(s2.NbNotEmptyChars()); 
  
            Console.WriteLine(s1.Equals(s2)); 
        } 
    } 
  
    struct MaStructure 
    { 
        public string FullName { get; set; } 
  
        public MaStructure(string firstName, string lastName) 
        { 
            FullName = $"{firstName} {lastName}"; 
        } 
  
        public int NbNotEmptyChars() 
        { 
            if (string.IsNullOrWhiteSpace(FullName)) 
            { 
                return 0; 
            } 
            else 
            { 
                return FullName.Replace(" ", "").Length; 
            } 
        } 
    } 
}

Du coup, un "Value Object", existe déjà dans .NET et s'appelle struct...

Le seul truc qui manque, c'est qu'on ne peut pas initialiser une proriété readonly directement avec un new MaStructure() { FullName = "Toto" } mais je ne vois pas ce qui empêchait de mettre "init" sur les structures aussi...
Dans quel cas un "class data" est-il différent d'un "struct" donc toutes les propriétés sont readonly ?

Bref, je pige vraiment pas.
1  0 
Avatar de Programmator
Membre régulier https://www.developpez.com
Le 23/05/2020 à 15:54
Citation Envoyé par StringBuilder Voir le message

Le seul truc qui manque, c'est qu'on ne peut pas initialiser une proriété readonly directement avec un new MaStructure() { FullName = "Toto" } mais je ne vois pas ce qui empêchait de mettre "init" sur les structures aussi...
Dans quel cas un "class data" est-il différent d'un "struct" donc toutes les propriétés sont readonly ?

Bref, je pige vraiment pas.
Les classes et les structures ont aussi 2 différences majeures :
  • Les instances de classes sont stockées dans le tas, qui est une zone mémoire large gérée par le ramasse-miettes. Alors que les instances de structures sont stockées sur la pile et détruites automatiquement lorsqu'on sort de la portée.
  • Les classes sont dérivables, alors que les structures ne le sont pas.


Les classes data restent des classes et continuent donc de profiter de ces 2 caractéristiques propres aux classes.
De plus, en lisant l'article original de Microsoft, je crois comprendre que les classes data ont besoin de l'héritage dans certains scénarios (cf. chapitre Value-based equality and inheritance)
1  0 
Avatar de StringBuilder
Expert éminent https://www.developpez.com
Le 23/05/2020 à 16:04
En effet, bien vu pour l'héritage. J'avais pourtant l'exemple sous les yeux, je n'y avais pas pensé.

Par contre, pour la partie gestion de la mémoire, j'ai envie de dire :
- on s'en moque un peu (après tout, c'est la sauce interne du Framework, ça peut tout à fait changer d'une version à l'autre, voir même d'une implémentation à l'autre)
- mais surtout, je ne vois pas l'intérêt de stocker des value objects dans une zone mémoire gérée par le GC. En effet, vu que ce sont des objets valeur, il ne peut y avoir qu'une seule référence (c'est con de manipuler une référence d'un type value... c'est un peu dommage d'utiliser un objet valeur pour n'en manipuler que la référence. Et très peu de chance/raison de recréer le même objet exactement, (et vérifier qu'il est identique à un détruit précédemment prendra de toute façon autant de temps que de le récupérer) sinon, pourquoi l'avoir détruit ?
1  0 
Avatar de François DORIN
Expert éminent sénior https://www.developpez.com
Le 24/05/2020 à 11:04
Citation Envoyé par StringBuilder Voir le message
Y'a un truc que j'ai pas bien compris avec le "record" (mot clé data).

Du coup, c'est quoi la différence entre un "struct" et un "class data", mise à part que le "class data" est readonly ?
A priori, un class data reste une classe. Donc passage par référence. Le passage en tant que paramètre dans une méthode ou la copie dans une variable serait donc bien rapide que dans le cas d'une struct, notamment lorsqu'il y a beaucoup d'attributs.

L'objectif c'est de donner un comportement de type "valeur" à une classe. L'égalité, par exemple, se base non plus sur les références, mais bien sur la valeur des attributs sous-jacents.

Citation Envoyé par Programmator

Les instances de classes sont stockées dans le tas, qui est une zone mémoire large gérée par le ramasse-miettes. Alors que les instances de structures sont stockées sur la pile et détruites automatiquement lorsqu'on sort de la portée.
Partiellement inexacte. Les types valeur peuvent être allouées sur le tas et non sur la pile dans certaines condicitions. Par exemple, en cas de boxing :
Code : Sélectionner tout
1
2
object monEntier = 3; // alloué sur le tas !
1  0 
Avatar de Programmator
Membre régulier https://www.developpez.com
Le 26/05/2020 à 18:53
Citation Envoyé par François DORIN Voir le message
A priori, un class data reste une classe. Donc passage par référence. Le passage en tant que paramètre dans une méthode ou la copie dans une variable serait donc bien rapide que dans le cas d'une struct, notamment lorsqu'il y a beaucoup d'attributs.

L'objectif c'est de donner un comportement de type "valeur" à une classe. L'égalité, par exemple, se base non plus sur les références, mais bien sur la valeur des attributs sous-jacents.

Partiellement inexacte. Les types valeur peuvent être allouées sur le tas et non sur la pile dans certaines condicitions. Par exemple, en cas de boxing :
Code : Sélectionner tout
1
2
object monEntier = 3; // alloué sur le tas !
Je partage tout à fait ce que tu dis François concernant le comportement de type valeur. C'est d'ailleurs déjà ce qui existe avec le type string, qui se comporte comme un type valeur bien que ce soit un type référence.

Concernant l'allocation mémoire, même dans le boxing, la règle des types valeurs stockés sur la pile reste vraie. C'est un mécanisme que j'ai bien étudié pour faire mon cours C# et voici ce que j'ai compris :
3 est un type valeur qui est donc stocké sur la pile.
monEntier étant de type object, il doit obligatoirement référencer un emplacement du tas. S'il pointait sur un emplacement de la pile, cela créerait un défaut de sécurité potentiel. Par conséquent, le runtime réserve un bloc de mémoire sur le tas, y copie la valeur de l'entier 3, puis référence cette copie dans l’objet monEntier. Ceci est illustré par le schéma suivant :



La règle types valeurs stockés sur la pile et types références stockés sur le tas est ainsi toujours respectée.
1  0 
Avatar de zero_divide
Membre à l'essai https://www.developpez.com
Le 22/05/2020 à 19:08
Moi qui structure mon code selon le "Domain-driven design (DDD)", c’est évidemment pour représenter un Value Object.
1  1