Navigation

Inscrivez-vous gratuitement
pour pouvoir participer, suivre les réponses en temps réel, voter pour les messages, poser vos propres questions et recevoir la newsletter

  1. #1
    Rédacteur

    [Article] Présentation de la classe Tuple du .NET Framework 4
    Bonjour à tous,

    Avec l'arrivée du .NET Framework 4 de Microsoft, de nombreuses classes ont été introduites. Une de ces classes est la classe "System.Tuple" et qui permet de stocker un ensemble d'éléments de types différents tout en gardant une sécurité au niveau du typage grâce à la généricité. L'avantage est que vous allez pouvoir utiliser ce type en retour ou comme argument de vos méthodes. Les développeurs Python devraient déjà comprendre de quoi je parle. Pour les autres, vous pourrez découvrir cette classe plus en détails dans le dernier article que je viens d'écrire et qui s'intitule "Présentation de la classe Tuple du .NET Framework 4".

    http://jlambert.developpez.com/tutor...t-framework-4/

    Bonne lecture !
    Jérôme Lambert
    Développeur, Architecte, Rédacteur & Fan technologies Microsoft
    Ma boite informatique | Mon profil LinkedIn

  2. #2
    Membre éprouvé
    Ca c'est la grande classe

  3. #3
    Membre confirmé
    Article bien sympathique.

    Merci

  4. #4
    Membre actif
    Merci beaucoup pour l'article sur les tuples qui est très interressant.

    Néamoins j'ai une question à poser.
    Dans le cas où on a plusieurs variables à retourner pourquoi les ref ne sont pas bien ?

  5. #5
    Membre éprouvé
    question de lisibilité du code

    (PS : J'ai 5 ans de python derrière moi, je vois de plus en plus le C# s'en rapprocher et c'est vraiment agréable )

  6. #6
    Rédacteur

    Citation Envoyé par anthyme Voir le message
    question de lisibilité du code
    Je n'ai pas mieux comme réponse
    Jérôme Lambert
    Développeur, Architecte, Rédacteur & Fan technologies Microsoft
    Ma boite informatique | Mon profil LinkedIn

  7. #7
    Membre expérimenté
    les tuples, c'est le nec plus ultra pour les coordonnées, (x,y) ou (x,y,z) lors de la programmation d'application graphique.

  8. #8
    Membre confirmé
    Vous trichez un peu dans votre exemple car
    Code :Sélectionner tout -Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    struct TypedObjects
    {
    	private int _MyIntParam;
    	private bool _MyBoolParam;
    	private string _MyStringParam;
     
    	public int MyIntParam
    	{
    		get { return _MyIntParam; }
    		set { _MyIntParam = value; }
    	}
     
    	public bool MyBoolParam
    	{
    		get { return _MyBoolParam; }
    		set { _MyBoolParam = value; }
    	}
     
    	public string MyStringParam
    	{
    		get { return _MyStringParam; }
    		set { _MyStringParam = value; }
    	}
    }
    peut aussi s'écrire
    Code :Sélectionner tout -Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    struct TypedObjects
    {
    	public int MyIntParam { get; set; }
     
    	public bool MyBoolParam { get; set; }
     
    	public string MyStringParam { get; set; }
    }


    Autrement ce serait bien aussi de nommer ses propriétés comme bon nous semble au lieu de "ItemX"...

    comme on peut déjà le faire avec "var" sauf seulement en local.

    Pour que ça fonctionne, je remplacerai donc "Tuple<>" par un "var<>"
    Code :Sélectionner tout -Visualiser dans une fenêtre à part
    1
    2
    3
    4
    var<int, bool, string> GetObjectsVar3()
    {
    	return new {Value = 1, Conclusion=true, Message="Bonjour"};
    }
    Ensuite... ce n'est pas moi qui pourrai vous dire si c'est entièrement viable après mes 3 secondes de réflexions !

  9. #9
    Rédacteur

    Citation Envoyé par ijk-ref Voir le message
    Vous trichez un peu dans votre exemple car
    Code :Sélectionner tout -Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    struct TypedObjects
    {
        private int _MyIntParam;
        private bool _MyBoolParam;
        private string _MyStringParam;
     
        public int MyIntParam
        {
            get { return _MyIntParam; }
            set { _MyIntParam = value; }
        }
     
        public bool MyBoolParam
        {
            get { return _MyBoolParam; }
            set { _MyBoolParam = value; }
        }
     
        public string MyStringParam
        {
            get { return _MyStringParam; }
            set { _MyStringParam = value; }
        }
    }
    peut aussi s'écrire
    Code :Sélectionner tout -Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    struct TypedObjects
    {
        public int MyIntParam { get; set; }
     
        public bool MyBoolParam { get; set; }
     
        public string MyStringParam { get; set; }
    }
    (thomas, c'est toi ?!!! => private joke avec l'équipe dvp )

    Ouch, j'ai déjà du résister à un débat sur la même remarque en interne avec les membres de developpez.com... Voila qu'on me relance. Alors, je n'ai pas essayé de tricher en écrivant la classe comme je l'ai fait. Si j'ai préféré ne pas utiliser des propriétés auto, c'est uniquement parce que c'est une raccourci du langage que j'essaye d'éviter au maximum pour la bonne et simple raison que si un jour une propriété auto doit être un peu plus "intelligente" au niveau du get/set, je n'ai pas envie de passer mon temps à en faire une propriété explicite avant de pouvoir faire mon changement.

    Si je te demandais l'utilité de faire ça, tu me répondrais que c'est un raccourci d'écriture. Je suis au courant et donc, retour à mon argument du dessus. Sans compter que faire une propriété explicite est à peine plus long (on écrit la variable membre => on encapsule et comme ça pas besoin d'écrire la propriété sois-même).

    Pour moi, ça n'a rien à voir avec les nouvelles fonctionnalités de C# 3 comme le var, les objets anonymes, etc... Car même si au premier abord, on pourrait se dire que c'est juste pour rendre le développeur plus fainéant, c'est absolument pas l'objectif car en rapport avec Linq, ces évolutions ont toutes du sens.

    Maintenant, il n'est pas impossible que j'ai manqué quelque chose avec les propriétés auto. Un argument qui démontrerait que si l'équipe C# a décidé d'apporter cette fonctionnalité, c'est parce que sans, telle chose du FX 3.5 n'aurait pas été possible. Là, je remettrai en question ma décision

    Citation Envoyé par ijk-ref Voir le message
    Autrement ce serait bien aussi de nommer ses propriétés comme bon nous semble au lieu de "ItemX"...

    comme on peut déjà le faire avec "var" sauf seulement en local.

    Pour que ça fonctionne, je remplacerai donc "Tuple<>" par un "var<>"
    Code :Sélectionner tout -Visualiser dans une fenêtre à part
    1
    2
    3
    4
    var<int, bool, string> GetObjectsVar3()
    {
        return new {Value = 1, Conclusion=true, Message="Bonjour"};
    }
    Ensuite... ce n'est pas moi qui pourrai vous dire si c'est entièrement viable après mes 3 secondes de réflexions !
    var n'est pas un type. Ca me pique les yeux de voir cette proposition

    Si ça t'intéresse, voici l'explication de microsoft qui explique pourquoi ils ont choisi comme noms Itemx :

    For languages that provide syntax for interacting with tuples, the names of the properties used to access each element aren't very interesting, since they are shielded from the developer. This is a very important question for languages like C#, where you have to interact with the type directly. We started with the idea of using Item1, Item2, and so on as the property names for the elements, but we received some interesting feedback from our framework design reviewers. They said that while these property names make sense when someone thinks about them at first glance, it gives the feeling that the type was auto-generated, instead of designed. They suggested that we name the properties First, Second, and so on, which felt more accessible. Ultimately, we rejected this feedback for a few reasons: first, we liked the experience of being able to change the element you access by changing one character of the property name; second, we felt that the English names were difficult to use (typing Fourth or Sixth is more work than Item4 or Item6) and would lead to a very weird IntelliSense experience, since property names would be alphabetized instead of showing up in numerical order.
    Source : http://msdn.microsoft.com/en-us/maga.../dd942829.aspx
    Jérôme Lambert
    Développeur, Architecte, Rédacteur & Fan technologies Microsoft
    Ma boite informatique | Mon profil LinkedIn

  10. #10
    Membre éprouvé
    Un tuple ce n'est pas une classe ou une structure, c'est une liste en lecture seule qui contient des objets de différents types

  11. #11
    Membre confirmé
    Citation Envoyé par Jérôme Lambert Voir le message
    Ouch, j'ai déjà du résister à un débat sur la même remarque en interne avec les membres de developpez.com...
    T'inquiètes je ne vais pas relancer le débat. Et puis je ne suis pas encore vraiment sûr de l'utilité de cette écriture.

    Citation Envoyé par Jérôme Lambert Voir le message
    var n'est pas un type. Ca me pique les yeux de voir cette proposition
    Alors là on va éviter de jouer sur les mots. "var" n'est bien sûr pas un type et mon "var<>" ne l'est pas non plus

    C'est juste qu'évidement lorsque j'ai pris connaissance avec "var"... j'ai tout de suite voulu l'essayer en sortie d'une méthode

    Pour exactement la même utilisation que "Tuple" : ne pas définir une class/struct pour une utilisation unique et avec ces propriétés en lecture-seule.

    Seulement ce serait un avantage indéniable de nommer les sorties car comme tu l'as dit : "on s'y perd un peu quand il y en à trop dans les itemX"

    Peut être qu'il faut privilégier une autre forme d'écriture genre :
    Code :Sélectionner tout -Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    public (int, string) Methode(float x, double y)
    {
        return new {Value=3, Key="toto"};
    }
     
    // ou
     
    public (int Value, string Key) Methode(float x, double y)
    {
        return(3, "toto");
    }
    On nomme bien les variables d'entrées, autant faire de même avec les variables de sorties. Ce serait une écriture bien plus agréable que les "out"

    Cette construction me semble viable car elle contraint toujours l'utilisation de "var" en local.
    Citation Envoyé par anthyme Voir le message
    Un tuple ce n'est pas une classe ou une structure, c'est une Liste en lecture seule qui contient différent types d'objets
    T'es sûr de toi qu'une liste intervient là dedans en interne !?

    Quelle idée d'avoir sortie "Tuple" ! Maintenant je voudrais forcement qu'ils aillent jusqu'au bout de cette logique !

  12. #12
    Membre éprouvé
    Citation Envoyé par ijk-ref Voir le message
    T'es sûr de toi qu'une liste intervient là dedans en interne !?

    Quelle idée d'avoir sortie "Tuple" ! Maintenant je voudrais forcement qu'ils aillent jusqu'au bout de cette logique !
    Je n'ai pas dit que c'était une liste en interne mais que l'approche d'utilisation des tuples ressemble a une liste dans son utilisation (une séquence ordonné d'objets)

  13. #13
    Membre confirmé
    Au fait juste comme ça...

    Connaissez-vous la raison méthodologique/physique qui empêche l'utilisation du mot "var" à la sortir d'une méthode ?

    Car si c'était possible il n'y aurait pas besoin de "Tuple"

  14. #14
    Membre éprouvé
    pour la même raison qu'on ne peux pas faire:

    Code :Sélectionner tout -Visualiser dans une fenêtre à part
    1
    2
    var a;
    a = "toto"


    var a l'air dynamique mais il n'en n'est rien, c'est toujours du typage static, il est juste implicite.

    Et une variable ou une méthode doit définir son type à sa définition

  15. #15
    Rédacteur

    Je pense que ça devrait être possible de pouvoir utiliser un var "type" de retour d'une méthode.

    Code :Sélectionner tout -Visualiser dans une fenêtre à part
    1
    2
    3
    4
    var MaVarMethode()
    {
       return new {PropString = "hello", PropInt = 2010};
    }


    A la compilation, mon type anonyme donnera une classe concrète, c'est le principe des objets anonymes.

    Après, pourquoi n'est-il pas possible d'utiliser ce type d'écriture ? Il n'y que les équipes de Microsoft qui ont la réponse suite à leurs très nombreuses deiscussions brainstorming, design, etc.

    Après, je suis pas super fan quand j'imagine une telle fonctionnalité en C# car je vois déjà les dérives arriver avec bon nombre de développeurs (je parle pour moi aussi) qui, par parresse, vont commencer à mettre des var partout en type de retour des méthodes. Après, on aura un autre développeur qui devra utiliser (voir améliorer) ce que le premier a fait... Il fait comment pour avoir la documentation de cette classe ? Et s'il a besoin de rajouter une propriété calculée ? Ou des méthodes ?
    Jérôme Lambert
    Développeur, Architecte, Rédacteur & Fan technologies Microsoft
    Ma boite informatique | Mon profil LinkedIn

  16. #16
    Membre confirmé
    Citation Envoyé par Jérôme Lambert Voir le message
    ... Il fait comment pour avoir la documentation de cette classe ?
    Je suis bien d'accord qu'il y a un p'tit problème pour connaitre la signature exacte avec seulement l'entête d'une méthode. Donc "var" semble clairement ne pas être la bonne solution.

    Mais peut être qu'ils ont oublié de nous fournir un outil "public" avec leur définition de "var" - l'autre qui ce la pète point com

    Par exemple comment fait-on pour construire une classe vérifiant :

    Code :Sélectionner tout -Visualiser dans une fenêtre à part
    TClass o = new TClass() {Key = 1, Value = "toto"};

    Tout en ayant "Key" et "Value" en lecture seule !?

    ...Oui je sais j'ai l'air de m'égarer du sujet Tuple... mais je l'impression que le problème est là. S'il ne nous manquait pas cette outil la définition de Tuple deviendrait (peut-être) inutile.

  17. #17
    Membre confirmé
    J'ai la solution !

    Il faudrait simplement rajouter la déclaration de types anonymes !

    On peut déjà en initialiser... alors rajouter sa déclaration devrait même harmonisé le sens de "var"

    Je propose comme écriture :
    Code :Sélectionner tout -Visualiser dans une fenêtre à part
    (int Key, string Value) o;
    Voila ! J'ai déclaré "o" de type... le truc entre parenthèses... un type parfaitement définit mais sans nom.

    Ainsi "o" s'initialise normalement :
    Code :Sélectionner tout -Visualiser dans une fenêtre à part
    o = new {Key = 1, Value = "toto"};


    OK !? Mais à quoi ça sert !?

    Et bien maintenant on peut déclarer une méthode de façon claire et précise remplaçant avantageusement toutes les bidouilles de Tuple :
    Code :Sélectionner tout -Visualiser dans une fenêtre à part
    1
    2
    3
    4
    public (int Key, string Value) MaMethode(double x)
    {
        return new {Key = 1, Value = "toto"};
    }
    Avouez que ça fait une belle signature toute propre ! Elle reste parfaitement fonctionnelle car en interne la sortie est un type classique (anonyme mais classique)

    La déclaration est parfaitement "explicite" et n'entraine donc aucunement les complications du mot "var" (déclaration implicite) qui ne change pas de rôle.

    Ce ne serait pas mieux non !?

    Note 1 : Tuple a des outils pour la comparaison... là je ne sais pas... mais il me semble que le Linq a ce qu'il faut pour gérer nativement les types anonymes... non ?

    Note 2 : Aucune utilité... mais en regardant le fonctionnement interne des types anonymes (grâce à la Reflexion), je pense que "o" serait aussi initialisable comme ceci :
    Code :Sélectionner tout -Visualiser dans une fenêtre à part
    o = new (int Key, string Value)(1, "toto");


    Note 3 : la déclaration "(Type1 nom1, Type2 nom2, ...)" reste bien sûr à être étudié pour éviter de possibles confits.

  18. #18
    Membre averti
    L'article présente bien le sujet, on comprend vite le pourquoi du coment. En revanche je garde un oeil critique sur l'usage que peut être fait d'une telle classe.

    L'objet Tuple est fortement typé, mais les accesseurs (Item1, Item2....) ne sont vraiment pas explicite. En réalité on gagne d'un côté pour perdre d'un autre côte = On développe plus vite, mais on perd en lisibilité et maintenance.
    Lorsqu'on manipule une classe, on travaille avec des propriétés qui ont un sens et qui parle de suite :


    Code :Sélectionner tout -Visualiser dans une fenêtre à part
    1
    2
    monObj.Age;
    monObj.IsValid;


    c'est différent de :

    Code :Sélectionner tout -Visualiser dans une fenêtre à part
    1
    2
    monObj.Item1
    monObj.Item2

  19. #19
    Membre confirmé
    Citation Envoyé par oyigit Voir le message
    L'objet Tuple est fortement typé, mais les accesseurs (Item1, Item2....) ne sont vraiment pas explicite. En réalité on gagne d'un côté pour perdre d'un autre côte = On développe plus vite, mais on perd en lisibilité et maintenance (...)
    D'où l'intérêt de ce que j'ai écrit juste au dessus

  20. #20
    Membre averti
    Effectivement, ça pourrait être une bonne solution. Il reste néanmoins des problèmes de lisibilité. Lorsqu'on manipule un type anonyme, on ne sait pas ce qu'on manipule non plus :

    Exemple :

    Code :Sélectionner tout -Visualiser dans une fenêtre à part
    ParametresRechercheClients (string nom, int age)


    Lorsqu'on manipule un objet de type ParametresRechercheClients, on sait (et visual studio nous le montre bien) qu'on traite des paramètres de recherche de patients, on sait à quoi est destiné l'objet..., alors qu'avec un type anonyme...

###raw>template_hook.ano_emploi###