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 !

Microsoft a dévoilé la feuille de route de C # 7.1, C # 7.2 et C # 8.0
Et propose quelques améliorations à son langage

Le , par Stéphane le calme

43PARTAGES

10  0 
C # 7.1

async Task Main()

Les mots clés async et await, qui ont été apportés par C # 5.0 facilitent l’écriture du code qui appelle des systèmes externes, ou fait des E/S, sans bloquer un thread. Cela rend les applications Web évolutives et conserve la réactivité des IU d’applications.

Cependant, une fois qu'une partie de votre code est asynchrone, tout ce qui implique ce code doit également devenir asynchrone. Lorsque votre application d'hébergement est une application de console ou un service Windows, cela pose un problème. Vous pouvez écrire async void Main, mais cela signifie que, dès que vous arrivez à votre premier await, l’application entière se termine.

La raison ? async void, qui agit comme un mécanisme de prévention des incendies. Étant donné que vous ne pouvez pas retourner une Task de Main, vous devrez utiliser quelque chose comme AsyncContext depuis la bibliothèque AsyncEx.

Microsoft explique que cela ne sera plus nécessaire : le compilateur et le framework reconnaîtront et exécuteront correctement une méthode Async Task Main.

Les expressions default :

Il s'agit simplement d'une amélioration de quelque chose qui a été supporté depuis C # 2.0 et l'avènement des génériques, en 2005. Il est sous forme de default (T), où T est bien sûr un type. Pour les types de référence, il représente null, et pour les types de valeurs tels que int, il représente la valeur par défaut, non initialisée, de ce type.

La nouvelle fonctionnalité est que, lorsque le type de T peut être déduite, il n'est plus nécessaire de le spécifier.

En clair, au lieu d’écrire ceci

Code C# : Sélectionner tout
int x = default(int);

Vous pourrez écrire ceci

Code C# : Sélectionner tout
int x = default;


Bien sûr, cela s'étend également à d'autres usages de default, tels que les déclarations de retour, les valeurs par défaut pour les arguments, et, en développant le point précédent, les expressions ternaires.

Pour illustrer, ceci sera valide dans une future version de C #

Code C# : Sélectionner tout
var x = flag ? 1: default;
:
Déduction des tuples

Supposons que vous voulez créer le tuple (string Nom, string Prenom) et que vous avez déjà des variables locales appelées Nom et Prenom. Vous devez écrire quelque chose comme ceci :
var t = (fNom: Prenom, SecondNom: SecondPrenom);
Cette fonctionnalité va déduire les noms des éléments de tuple à partir de leur expression d'initialisation, un peu comme ce que vous pouvez faire avec des types anonymes.

Code C# : Sélectionner tout
1
2
3
var t = (Nom, SecondNom); 
  
Console.WriteLine($"Salut, {t.Nom}!");

C # 7.2

Références read-only

Ici, il s’agit de donner à C # la possibilité d'utiliser des paramètres const-like pour améliorer les performances. Connu sous le nom de « paramètres réellement définis » ou « paramètres » simples, ceux-ci permettent de transmettre de grandes structures par référence tout en ne permettant pas qu'elles soient mutées.

C # 8.0

Types de référence nullables

L'équipe responsable du développement de C # a, pour l'instant, choisi de faire en sorte que tous les types de référence deviendront non annulables par défaut, et vous pouvez faire en sorte qu’un type de variable soit nullable en vous servant de “?”. L'utilisation d'une variable non nulle qui pourrait être nulle (car vous ne l'avez pas vérifiée si elle avait déjà pris cette valeur) entraînera un avertissement, tout en attribuant la valeur d'une variable nulle à celle qui n'est pas nullable.

Petit exemple d’illustration

Code C# : Sélectionner tout
1
2
3
4
5
6
7
// bar est nullable parce que son type est string? 
void Foo(string? bar)   
{ 
    string baz = bar;  
    // ceci va générer un avertissement parce que baz est non-nullable  
    // mais bar est nullable 
}
Pour résoudre ce problème, il suffit de vérifier que bar n’est pas null

Code C# : Sélectionner tout
1
2
3
4
5
6
7
void Foo(string? bar)   
{ 
    if (bar == null) 
        throw new ArgumentNullException(nameof(bar)); 
  
    string baz = bar;  
}

Source : feuille de route

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

Avatar de tomlev
Rédacteur/Modérateur https://www.developpez.com
Le 21/06/2017 à 14:30
Citation Envoyé par ijk-ref Voir le message
Faut être un peu de mauvaise foi
Merci d'éviter les attaques personnelles. Ce n'est pas parce que je ne suis pas d'accord avec toi que je suis de mauvaise foi. Tu as le droit de préférer ta syntaxe, et moi j'ai le droit de la trouver toute pourrie. Si tu veux forker le compilateur C# pour implémenter ça, libre à toi...

Pour ma part, j'ai dit ce que j'avais à dire sur ce sujet, et si c'est pour que ma bonne foi soit remise en cause, je n'ai aucune envie de continuer cette discussion.
4  0 
Avatar de François DORIN
Expert éminent sénior https://www.developpez.com
Le 15/11/2018 à 15:31
Citation Envoyé par ijk-ref Voir le message
Au contraire pour moi c'est une grande force d'accepter de corriger une GROSSE erreur où tellement d'autres seraient rester sur "oui mais on a toujours fait comme ça", "t'es un mauvais programmeur pour que ça te dérange"
Je ne dis pas que ce n'est pas une erreur. Je dis que corriger les choses maintenant au lieu de les avoir prévu dès le début va provoquer des incompatibilités. C# se retrouve donc a être comme PHP ou Python, où une montée de version majeure induit un cassage de la compatibilité. Et que ça, c'est aussi une très grosse erreur (peut être même plus que l'erreur que l'on souhaite corriger). Jusqu'à présent, l'ajout de nouvelles fonctionnalités s'était toujours fait de manière compatible.
3  0 
Avatar de tatayo
Expert éminent https://www.developpez.com
Le 14/11/2018 à 17:37
J'ai un petit problème avec l'implémentation par défaut dans une interface.
C# n'implémente pas l'héritage multiple, car "on ne sait pas quoi faire si une classe hérite de 2 classes qui implémentent la même méthode".

Quid d'une classe qui hérite de 2 Interfaces qui implémentent la même méthode ? On se retrouve avec le même "problème".

Concernant le "range", le point qui me chagrine est que le comptage part de 0 au début de la chaine, et de 1 à la fin.
Code C# : Sélectionner tout
1
2
3
4
5
  
Index i1 = 1;  // number 1 from beginning 
Index i2 = ^1; // number 1 from end 
int[] a = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 }; 
Console.WriteLine($"{a[i1]}, {a[i2]}"); // "1, 9"

Dans cet exemple, l'indice 1 est le second caractère, et l'indice ^1 le dernier. Pourquoi ce n'est pas ^0 ?

Tatayo.
2  0 
Avatar de tomlev
Rédacteur/Modérateur https://www.developpez.com
Le 16/06/2017 à 23:41
A noter que si les choses sont à peu près figées pour C# 7.1, ce n'est pas le cas pour les versions suivantes (les features sont encore à l'état de proposition ou de prototype).

Une autre feature très intéressante envisagée pour C# 8, c'est les méthodes par défaut dans les interfaces, un peu comme en Java 8. Ça permet de mettre dans une interface une méthode avec une implémentation. L'intérêt est multiple :
  • une classe qui implémente l'interface n'est pas obligée d'implémenter elle-même ces méthodes, puisqu'une implémentation par défaut existe
  • une classe qui implémente l'interface peut redéfinir ces méthodes, par exemple si elle peut en faire une implémentation plus efficace que celle par défaut
  • on peut ajouter des méthodes par défaut à une interface sans que ce soit un breaking change (normalement, ajouter un membre à une interface d'une API publique est un breaking change, puisque les classes qui implémentent déjà l'interface doivent être modifiées)
  • ça apporte à C# une forme allégée d'héritage multiple (allégée car une interface ne peut pas déclarer de champs, seulement des méthodes, propriétés ou événements)
1  0 
Avatar de tomlev
Rédacteur/Modérateur https://www.developpez.com
Le 20/06/2017 à 11:51
Citation Envoyé par ijk-ref  Voir le message
Bonjour j'aimerai bien savoir ce que vous penseriez d'une amélioration de langage bien plus souple et puissante concurrente à la gestion des exceptions et des variables de sorties 'out' ?

J'en pense que tu avais déjà mentionné cette idée il y a quelques mois, que j'avais trouvé que c'était une très mauvaise idée, et que mon avis n'a pas changé depuis . D'une part parce que c'est incompréhensible, et d'autre part parce que ce n'est pas du tout cohérent avec la syntaxe existante du langage.

D'ailleurs en C# 7 on peut déjà faire des choses tout à fait propres et lisibles pour ce genre de situation :

Code C# : Sélectionner tout
1
2
3
4
5
6
7
8
if (TryParse("42", out var i)) 
{ 
    // i vaut 42 
} 
else 
{ 
    ... 
}

Tu peux toujours aller proposer ton idée sur Github, mais je doute qu'elle soit accueillie très favorablement...
1  0 
Avatar de Noxen
Membre expérimenté https://www.developpez.com
Le 14/11/2018 à 17:43
Citation Envoyé par Kikuts Voir le message
L'article ne parle pas des interfaces qui pourront porter une implémentation de base ????!!!!
Pourtant c'est une des features que je préfère !

Exemple (codé sans passer par IDE dsl)

Code : Sélectionner tout
1
2
3
4
5
6
7
interface IViewModel : INotifyPropertyChanged
{
 void RaisePropertyChanged(string propertyName)
{
    PropertyChanged?.invoke(propertyName);
}
}
Ça c'est justement un cas où ça me paraîtrait inapproprié. D'un point de vue fonctionnel un IViewModel ne devrait pas permettre à son consommateur de lever lui-même l'événement, après tout seul le ViewModel peut dire si une de ses propriétés à réellement changé sa valeur (puisqu'il pourrait par exemple bloquer l'affectation d'une valeur invalide). Ce genre de méthode n'a ça place que dans la structure interne d'une classe et ne devrait pas être dans une interface. Si on veut factoriser ce code on le ferait dans une classe de base (éventuellement abstract) qui serait héritée par d'autres classes spécifiques. En revanche on pourrait avoir, j'imagine, une méthode GetModelVersion(), qui donnerait des informations sur le modèle de données sous-jacent, et renverrait une valeur par défaut si ce n'est pas géré par une implémentation spécifique.

En outre il me semble que ce mécanisme devait être introduit pour permettre de faire évoluer une interface sans introduire de breaking change auprès des "implémenteurs" (qui autrement ne seraient plus compatibles avec leurs propres consommateurs). Il me semble que l'utiliser pour factoriser du code constitue un peu un détournement de l'intention de départ.
1  0 
Avatar de WaterTwelve21
Membre confirmé https://www.developpez.com
Le 19/06/2017 à 9:25
Je ne connais pas C# mais sauf erreur de ma part Java avait rajouté la généricité, la création des opérateurs...à la longue il faut faire gaffe cela va devenir du C++
Peut-être que c'est parce que ca fait bien longtemps que la généricité et la création des opérateurs ont été mis en place. Avec c#7 il n'y a pas de révolutions à proprement parler mais on ressent la volonté de toujours améliorer le quotidien du developpeur et puis les tuples les méthodes aux retour multiple etc ... c'est quand même pas mal.

C'est presque dommage que ca aille si vite ( ou que les entreprises ne suivent pas ) .
0  0 
Avatar de worm83
Membre éprouvé https://www.developpez.com
Le 20/06/2017 à 12:15
J'avais pas très bien compris le "ckeck nullable" de c# 8, tel que tu l'avais présenté.

Le but n'est pas réellement de forcer les référence a ne plus être nullable, comme je l'ai compris dans ton papier (ce qui serait une hérésie), mais de forcer les développeur à vérifier le fait que celle-ci n'est pas "null".

Et pour le coup c'est très intéressant lorsque l'on monte une archi/Framework, en appliquant certaines convention à l'équipe, on peut forcer à appliquer une programmation "défensive" sur certains socle de l’application, ou au contraire laisser sous-entendre entendre que la valeur et les limites de celle-ci a déjà été vérifiée via les signatures d'interface et éviter une revérifications des limites.

Le langage suit une bonne évolution.

Concernant ta proposition ijk-ref, je suis de l'avis de Tom, pas du tout intéressé.

Merci pour ce post tom.
0  0 
Avatar de tomlev
Rédacteur/Modérateur https://www.developpez.com
Le 21/06/2017 à 3:04
Citation Envoyé par ijk-ref  Voir le message
Imaginez que vous aillez besoin d'une "méthode" devant retourner 1 valeur... mais pouvant être de 3 types différents... et qu'en bon "autiste" adepte du typage fort vous aimeriez avoir les outils pour que ce soit le compilateur qui se charge de cette vérification... quelle syntaxe aimeriez-vous avoir à votre disposition pour parfaire ce fantasme ?

Je vous montre la mienne :

Pourquoi un "index" pour représenter le type ?

Moi je te montre la mienne :

Code C# : Sélectionner tout
1
2
3
4
5
6
7
8
9
10
11
12
13
var result = MyEvents(mouseMove, mouseDown, keyDown); 
switch (result) 
{ 
  case MouseButtonEventArgs r: 
    label.Content = "button : " + r.MouseButton; 
    break; 
  case MouseEventArgs r: 
    label.Content = "location : " + r.GetPosition(this); 
    break; 
  case KeyEventArgs r: 
    label.Content = "key : " + r.Key; 
    break; 
}

C'est du C# 7, on peut déjà faire ça aujourd'hui sans inventer une nouvelle syntaxe bizarre.

Donc non, je suis toujours pas convaincu...

(note que j'ai réordonné les cases, parce que MouseButtonEventArgs hérite de MouseEventArgs, donc si MouseEventArgs est avant, il chopera aussi les MouseButtonEventArgs... c'est comme avec les catch, il faut intercepter l'exception la plus spécifique en premier)

Remplaçant avantageusement :

C'est très discutable... tu as le droit de préférer ça, mais personnellement je trouve ça affreux, et ça ne ressemble même pas à du C#.
0  0 
Avatar de SLE
Membre éclairé https://www.developpez.com
Le 26/06/2017 à 8:56
Dans l'exemple C# 8.0, quel est l'intérêt de déclarer un string? alors que le type string est déjà nullable par défaut ?
0  0