Envoyé par
ijk-ref
Je suis très étonné par le choix de "Deconstruct"
1 2 3 4 5
| public void Deconstruct(out double x, out double y)
{
x = this.X;
y = this.Y;
} |
Je comprends qu'en interne ils veuillent se reposer sur du C# "ancien" mais pour l'utilisateur final d'aujourd'hui le but des nouveaux "tuples" n'est-il pas justement d'éviter au maximum l'utilisation peu pratique et archaïque de "out" ?
C'est juste au niveau de la déclaration ; au niveau de l'utilisation, tu n'as pas besoin de
out. Et de toute façon c'est juste si tu veux ajouter à une classe la possibilité de la déconstruire, pour les tuples tu n'as rien à faire, c'est déjà fait.
Envoyé par
ijk-ref
L'utiliser sous cette forme me semblerait plus judicieuse :
public (double x, double y) Deconstruct() => (this.X, this.Y);
C'était ma première réaction, mais en fait il y a une bonne raison : avec la syntaxe choisie, tu peux avoir plusieurs méthodes Deconstruct, avec des signatures différentes :
1 2 3 4 5 6 7 8 9 10 11 12
| public void Deconstruct(out double x, out double y)
{
x = this.X;
y = this.Y;
}
public void Deconstruct(out double x, out double y, out double z)
{
x = this.X;
y = this.Y;
z = this.Z;
} |
Avec ce que tu proposes, ce ne serait pas possible, vu que tu ne peux pas avoir deux méthodes qui ne diffèrent que par le type de retour.
Envoyé par
ijk-ref
AMHA une autre direction comme avec un mécanisme d'"exception light" - quand la gestion d'exception classique n'est pas obligatoire ou trop lourde.
En introduisant par exemple deux nouveaux mots clés, un permettant une sortie incorrecte (sans lancer d'exception) d'une méthode et un autre pour la tester :
1 2 3 4
| if (try int i = int.ParseLight(s))
{
Console.WriteLine($"La chaine représente un entier de valeur {i}");
} |
J'aime bien le principe... tu peux le proposer sur le GitHub Roslyn
Envoyé par
ijk-ref
Et comme je réfléchis en même temps que j'écris... je pense même qu'il serait possible de transformer les Parses avec exceptions classiques pour qu'ils fonctionnent... classiquement et aussi dans un mode light se suffisant d'un simple test booléen comme le code au-dessus.
Le problème des méthodes Parse qui renvoient des exceptions, c'est que les exceptions ne sont pas seulement lourdes en terme de syntaxe, mais aussi en terme de performance. Lancer et catcher une exception, ça coûte cher...
Envoyé par
ijk-ref
Sinon avec C# 7 on doit pouvoir écrire cela (bon c'est un peu plus verbeux mais adieux les "out"
):
1 2 3 4
| if (!((bool error, int i) = int.ParseLight2(s)).error)
{
Console.WriteLine($"La chaine représente un entier de valeur {i}");
} |
Oula, pas sûr que ce soit plus lisible... Ce qui serait plus intéressant, c'est une méthode TryParse qui renvoie un
Nullable<int>, ça permettrait d'utiliser le pattern matching pour faire ça :
1 2 3 4
| if (int.TryParse(s) is int i)
{
...
} |
Envoyé par
ijk-ref
Autrement dans ton switch Pattern matching ça fonctionnerait un "
goto Circle c when c.Radius < 5" ?
Non, ça marche pas. Tu peux toujours faire un goto vers un
case <Constante>, mais pas vers un
case <Type>.
Envoyé par
ijk-ref
Sinon n'y aurait-il pas une petite faute dans ton exemple sur la généralisation du type de retour des méthodes asynchrones ? AMHA la variable "price" en attente n'est pas déclarée puisqu'avant elle est interne au if.
Non non, c'est correct. Pendant la phase de design il y a eu pas mal de discussions sur le scope d'une variable déclarée comme ça, mais la rendre interne au if posait trop de problèmes. Exemple type de pourquoi c'est problématique :
1 2 3 4 5 6 7 8
| if (!int.TryParse(s, out int i))
{
// i est défini, mais ça valeur n'a pas de sens puisque TryParse a échoué
}
else
{
// TryParse a réussi, mais i n'est pas défini
} |
Donc au final le scope de la variable est le scope parent du if.
0 |
0 |