IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)
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

C# Discussion :

Variable créée avec "var". Comment ça marche au juste ?


Sujet :

C#

  1. #1
    Expert éminent
    Avatar de StringBuilder
    Homme Profil pro
    Chef de projets
    Inscrit en
    Février 2010
    Messages
    4 153
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 45
    Localisation : France, Rhône (Rhône Alpes)

    Informations professionnelles :
    Activité : Chef de projets
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Février 2010
    Messages : 4 153
    Points : 7 403
    Points
    7 403
    Billets dans le blog
    1
    Par défaut Variable créée avec "var". Comment ça marche au juste ?
    Bonjour,

    Je suis plutôt "old school" en ce qui concerne la déclaration et le typage des données.

    Donc moi je suis resté à l'époque où on déclarait une variable de cette façon :

    Code csharp : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
     
    MyClass myinstance = new MyClass(parameters);

    Et donc, quand ma variable doit être une propriété :
    Code csharp : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
     
    class MyClass
    {
       AnotherClass myproperty;
     
       void SomeMethod()
       {
           myproperty = new AnotherClass(parameters);
       }
    }

    Sauf que là, les temps changes, et poussent comme des champignons des déclarations que je pensais presque avoir compris, mais qui finalement m'échappent totalement.

    Code csharp : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
     
    var service = new CalendarService(new BaseClientService.Initializer()
    {
       HttpClientInitializer = credential,
       ApplicationName = myname,
    });

    Je sais pas comment, mais ça marche. Ma variable "service" me semble non typée (ça ressemble vachement à la déclaration javascript par exemple).

    Et là, j'ai un cas où...
    Code csharp : 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
     
    class MyClass
    {
       private CalendarService service;
     
       void SomeMethod()
       {
          var service = new CalendarService(new BaseClientService.Initializer()
          {
             HttpClientInitializer = credential,
             ApplicationName = myname,
          });
       }
     
       void AnotherMethod()
       {
          service.DoSomething();
       }
    }

    Et le joli message :
    Warning 9 Field 'MyClass.service' is never assigned to, and will always have its default value null

    Qu'est-ce que je fois faire pour corriger le problème ?
    Car du coup, j'imagine que ma méthode "AnotherMethod" ne va jamais fonctionner...
    On ne jouit bien que de ce qu’on partage.

  2. #2
    Expert éminent
    Avatar de StringBuilder
    Homme Profil pro
    Chef de projets
    Inscrit en
    Février 2010
    Messages
    4 153
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 45
    Localisation : France, Rhône (Rhône Alpes)

    Informations professionnelles :
    Activité : Chef de projets
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Février 2010
    Messages : 4 153
    Points : 7 403
    Points
    7 403
    Billets dans le blog
    1
    Par défaut
    Hmmm, en relisant la documentation, j'ai un méchant doute...

    http://msdn.microsoft.com/en-us/library/bb383973.aspx

    En fait, si je comprends bien, du moment que j'ai pas une déclaration à la mords-moi-le-noeud de type anonyme, je connais déjà le type au moment de l'écriture du code.

    Du coup, si je vire simplement le mot-clé "var", ça corrige bien le problème ?

    Pas d'effet de bord caché ?

    Code csharp : 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
     
    class MyClass
    {
       private CalendarService service;
     
       void SomeMethod()
       {
          service = new CalendarService(new BaseClientService.Initializer()
          {
             HttpClientInitializer = credential,
             ApplicationName = myname,
          });
       }
     
       void AnotherMethod()
       {
          service.DoSomething();
       }
    }

    En tout cas, maintenant ça compile sans warning...

    J'ai bon ?
    On ne jouit bien que de ce qu’on partage.

  3. #3
    Membre expérimenté
    Homme Profil pro
    Développeur .NET
    Inscrit en
    Février 2007
    Messages
    871
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 39
    Localisation : Canada

    Informations professionnelles :
    Activité : Développeur .NET

    Informations forums :
    Inscription : Février 2007
    Messages : 871
    Points : 1 498
    Points
    1 498
    Par défaut
    Salut,

    T'as tout compris mais oublié un détail:

    le mot clé "var" est un "sucre" syntaxique au même titre que "Property" et sert juste à faire beau et ne pas retaper deux fois le type lorsque tu déclare et initialise une variable.

    En fait, si je comprends bien, du moment que j'ai pas une déclaration à la mords-moi-le-noeud de type anonyme, je connais déjà le type au moment de l'écriture du code.
    Tout à fait, d'ailleurs tu ne peux utiliser var que lorsque, sur la meme ligne tu créé ta variable et l'assigne.

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    class MyClass
    {
       private CalendarService service;
     
       void SomeMethod()
       {
          var service = new CalendarService(new BaseClientService.Initializer()
          {
             HttpClientInitializer = credential,
             ApplicationName = myname,
          });
       }
    Dans le code ci dessus, tu crée un champ "service", non renseigné, que tu veux assigner dans "SomeMethod". Mais le fait d'utiliser "var service = new CalendarService(new BaseClie..." indique que ce n'est pas le champ de ta classe que tu rempli mais une nouvelle variable locale d'ou le warning du compilateur.
    Tu aurais le meme problème si tu avais écrit:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    CalendarService  service = new CalendarService(new BaseClientService.Initializer()...
    Voila, tout simplement.

  4. #4
    Membre expert
    Avatar de GuruuMeditation
    Homme Profil pro
    .Net Architect
    Inscrit en
    Octobre 2010
    Messages
    1 705
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 49
    Localisation : Belgique

    Informations professionnelles :
    Activité : .Net Architect
    Secteur : Conseil

    Informations forums :
    Inscription : Octobre 2010
    Messages : 1 705
    Points : 3 568
    Points
    3 568
    Par défaut
    Vu que tu as un champ appellé "service" au niveau de ta classe, si tu ajoutes "var" devant dans ta méthode, ce n'est plus une assignation à ce champ, mais une déclaration et assignation d'une nouvelle variable locale appellée aussi "service".
    Ce qui explique le warning
    Microsoft MVP : Windows Platform

    MCPD - Windows Phone Developer
    MCPD - Windows Developer 4

    http://www.guruumeditation.net

    “If debugging is the process of removing bugs, then programming must be the process of putting them in.”
    (Edsger W. Dijkstra)

  5. #5
    Invité
    Invité(e)
    Par défaut
    Bonjour,

    En fait, le mot clé "var" revient à dire "le type de l'initialisation de la variable".

    Par exemple :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
     
    var fs = new FileStream("MonFichier.txt",FileMode.Open);
    //Equivaut exactement à cette déclaration :
    FileStream fs = new FileStream("MonFichier.txt",FileMode.Open);
    ou encore :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
     
    var fs = File.Open("MonFichier.txt",FileMode.Open);
    //Equivaut exactement à cette déclaration :
    FileStream fs = File.Open("MonFichier.txt",FileMode.Open);
    Pour aller plus loin, si tu as une fonction ainsi :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
     
    Stream GetAStream()
    {
       return File.Open("MonFichier.txt", FileMode.Open);
    }
    Alors dans ce cas :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
     
    var fs = GetAStream();
    //Equivaut exactement à :
    Stream fs = GetAStream();
    "var" est traduit à la compilation.

    Le principal intérêt de "var" est pour les types anonymes en effet, car sans le "var", il n'y a aucun moyen de refaire référence au type anonyme.
    Les types anonymes sont utilisés à fond comme "types intermédiaires" dans les requêtes Linq.

    Par exemple, la requête Linq suivante va implicitement créer un type anonyme intermédiaire sans que tu ne le voies :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
     
    DirectoryInfo dir = MonDossier();
    IEnumerable<FileInfo> mesFichiers =
    from f in dir.EnumerateFiles()
    let fileSize = f.Length
    where fileSize >= 50 && fileSize <= 500
    select f;
    Cette requête Linq me permet de trouver tous les fichiers dans mon dossier renvoyé par la fonction "MesDossiers()" qui ont une taille comprise entre 50 octets et 500 octets.

    Dans cette requête Linq, j'ai mis un "let" pour mémoriser la longueur du fichier actu pour ne pas rappeler la propriété "Length" dans le test, au cas où celle-ci serait un peu couteuse. Du coup, derrière, ça s'est traduit par un type anonyme intermédiaire.

    L'équivalent de cette requête Linq est :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
     
    IEnumerable<FileInfo> mesFichiers =
     dir.EnumerateFiles
     .Select(f => new { Source = f, fileSize = f.Length }) //Création du type anonyme intermédiaire
     .Where(o => o.fileSize >= 50 && o.fileSize <= 500) //Du coup, dans la lambda expression d'ici, la référence est celle du type anonyme
     .Select(o => o.Source);
    et donc à la fin, tu n'as plus de trace du type anonyme intermédiaire dans la visu code, mais si tu décompiles l'assemblage, tu le verras bien.

    Bon, alors là je suis un peu sorti du sujet "var" mais l'apparition des types anonymes est l'explication principale de l'apparition du mot clé "var".

    [EDIT] Merci Mickael. Au passage, j'ai corrigé une petite erreur que j'avais fais dans mon post.
    Dernière modification par Invité ; 05/06/2014 à 11h53.

  6. #6
    Membre expert
    Avatar de Pragmateek
    Homme Profil pro
    Formateur expert .Net/C#
    Inscrit en
    Mars 2006
    Messages
    2 635
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 37
    Localisation : France, Val de Marne (Île de France)

    Informations professionnelles :
    Activité : Formateur expert .Net/C#
    Secteur : Conseil

    Informations forums :
    Inscription : Mars 2006
    Messages : 2 635
    Points : 3 958
    Points
    3 958
    Par défaut
    Juste pour compléter un peu l'explication de Philippe qui est excellente (+1) : l'autre cas d'utilisation de var c'est pour raccourcir certaines déclarations qui deviennent très longues avec du LINQ, typiquement le GroupBy où tu te retrouves avec :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    IEnumerable< IGrouping < TKey, TSource > >
    Pour peu que ton TSource soit lui même un IDictionary<TKey, TValue> ça devient compliqué avec la moitié de la ligne consacrée à l'écriture du type.

    Mais en effet la raison fondamentale qui à elle seule explique var c'est l'ajout des types anonymes.

    En dehors de ces deux cas je déconseille très fortement l'usage de var qui obfusque le code en masquant l'information de typage qui est fondamentale : pas seulement à des fins de vérification par le compilateur mais aussi et surtout en tant que documentation pour les développeurs.

    Et les développeurs sans assez de recul et de maturité qui y goûtent on tendance à l'utiliser partout.
    Je vois régulièrement ce genre de code :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    for (var i = 0; i < n; ++i)
    Et c'est clairement n'importe quoi, on ne gagne même pas un caractère, on a juste obfusqué le code. :/
    Formateur expert .Net/C#/WPF/EF Certifié MCP disponible sur Paris, province et pays limitrophes (enseignement en français uniquement).
    Mon blog : pragmateek.com

  7. #7
    Modérateur
    Avatar de DotNetMatt
    Homme Profil pro
    CTO
    Inscrit en
    Février 2010
    Messages
    3 611
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 36
    Localisation : Etats-Unis

    Informations professionnelles :
    Activité : CTO
    Secteur : Finance

    Informations forums :
    Inscription : Février 2010
    Messages : 3 611
    Points : 9 743
    Points
    9 743
    Billets dans le blog
    3
    Par défaut
    Citation Envoyé par Pragmateek Voir le message
    Et les développeurs sans assez de recul et de maturité qui y goûtent on tendance à l'utiliser partout.
    Je vois régulièrement ce genre de code :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    for (var i = 0; i < n; ++i)
    Et c'est clairement n'importe quoi, on ne gagne même pas un caractère, on a juste obfusqué le code. :/
    Je ne suis pas d'accord avec toi, et je ne vois pas quel est lien avec la maturité. Ceci pour deux raisons :
    1. Si on est pas capable de savoir que dans ce cas i sera de type int, alors y'a quand même un souci
    2. Ca ne change rien, puisque qu'on mette explicitement int ou var on utilise le même nombre de lettres, et au-delà de cet argument que certains qualifieront de futile, on se retrouve bien avec un type int au final. C'est juste une question de préférence personnelle

    Sur le projet sur lequel je bosse actuellement, nous avons beaucoup de généricité, donc on se retrouve parfois avec des appels du genre (j'ai mis n'importe quoi, c'est juste pour l'exemple) :
    Code C# : Sélectionner tout - Visualiser dans une fenêtre à part
    IGenericObject<MaClasseA, IDictionary<MaClasseB, MaClasseC>> myVariable1 = new IGenericObject<MaClasseA, IDictionary<MaClasseB, MaClasseC>>();
    Ca prend déjà la moitié de la ligne ! Et en plus si on en a plusieurs d'affilé, c'est pas très sexy visuellement :
    Code C# : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    IGenericObject<MaClasseA, IDictionary<MaClasseB, MaClasseC>> myVariable1 = new IGenericObject<MaClasseA, IDictionary<MaClasseB, MaClasseC>>();
    IEnumerable<IDictionary<MaClasseA, MaClasseB>> myVariable2 = new IEnumerable<IDictionary<MaClasseA, MaClasseB>>();
    IEnumerable<IEnumerable<IDictionary<MaClasseA, IDictionary<MaClasseB, MaClasseC>>>> myVariable3 = new IEnumerable<IEnumerable<IDictionary<MaClasseA, IDictionary<MaClasseB, MaClasseC>>>>();
    Personnellement, je pense qu'il vaut mieux avoir un truc un peu plus lisible, et qui donne le même résultat :
    Code C# : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    var myVariable1 = new IGenericObject<MaClasseA, IDictionary<MaClasseB, MaClasseC>>();
    var myVariable2 = new IEnumerable<IDictionary<MaClasseA, MaClasseB>>();
    var myVariable3 = new IEnumerable<IEnumerable<IDictionary<MaClasseA, IDictionary<MaClasseB, MaClasseC>>>>();
    Surtout qu'il suffit de survoler la variable pour connaître son type en cas de doute.

    Mais bon encore une fois, c'est une question de préférence et éventuellement de norme de codage définie sur un projet. Au final, ça revient strictement au même.
    Less Is More
    Pensez à utiliser les boutons , et les balises code
    Desole pour l'absence d'accents, clavier US oblige
    Celui qui pense qu'un professionnel coute cher n'a aucune idee de ce que peut lui couter un incompetent.

  8. #8
    Membre éprouvé
    Homme Profil pro
    Architecte technique
    Inscrit en
    Septembre 2005
    Messages
    462
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Maine et Loire (Pays de la Loire)

    Informations professionnelles :
    Activité : Architecte technique
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Septembre 2005
    Messages : 462
    Points : 1 056
    Points
    1 056
    Par défaut
    Je suis d'accord avec tous vos points.


    Sinon j'ai la même pensé que DotNetMatt pour cette partie :
    Citation Envoyé par DotNetMatt Voir le message
    Je ne suis pas d'accord avec toi, et je ne vois pas quel est lien avec la maturité. Ceci pour deux raisons :
    1. Si on est pas capable de savoir que dans ce cas i sera de type int, alors y'a quand même un souci
    2. Ca ne change rien, puisque qu'on mette explicitement int ou var on utilise le même nombre de lettres, et au-delà de cet argument que certains qualifieront de futile, on se retrouve bien avec un type int au final. C'est juste une question de préférence personnelle
    Il n'y a pas grand chose à rajouter, les réponses sont déjà bien détaillées mais pour résumer "mes" bonnes pratiques avec var :
    J'utilise "var" plutôt que le "Type" quand il est clairement déclaré juste derrière (new...).

  9. #9
    Membre expert
    Avatar de Pragmateek
    Homme Profil pro
    Formateur expert .Net/C#
    Inscrit en
    Mars 2006
    Messages
    2 635
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 37
    Localisation : France, Val de Marne (Île de France)

    Informations professionnelles :
    Activité : Formateur expert .Net/C#
    Secteur : Conseil

    Informations forums :
    Inscription : Mars 2006
    Messages : 2 635
    Points : 3 958
    Points
    3 958
    Par défaut
    @DotNetMatt : concernant le raccourcissement des déclarations c'est bien plus lisible, donc code clairement de meilleure qualité, c'est le point que j'évoquais, donc là dessus on est d'accord.

    En revanche je persiste et signe pour son utilisation à tout va.

    1. Si on est pas capable de savoir que dans ce cas i sera de type int, alors y'a quand même un souci
    2. Ca ne change rien, puisque qu'on mette explicitement int ou var on utilise le même nombre de lettres, et au-delà de cet argument que certains qualifieront de futile, on se retrouve bien avec un type int au final. C'est juste une question de préférence personnelle
    Oui sur cet exemple trivial le type est évident.

    1. Mais donc autant faire au mieux si ça ne coûte pas plus cher.
    2. Le stagiaire ou le débutant voyant "var" va se poser des questions : comme en JS ? dynamique ? variant ?... autant lui faire gagner du temps, ainsi qu'à son tuteur.
    3. Exprimer son intention est fondamental (et pas qu'en programmation), je te donne un autre exemple où il n'y a pas débat :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    var reference1 = 100;
     
    Console.WriteLine("Intention non exprimee, le compilo joue aux devinettes : {0}", 1 / reference1);
     
    double reference2 = 100;
     
    Console.WriteLine("Intention clairement exprimée : {0}", 1 / reference2);
    Je te laisse découvrir le résultat.
    Formateur expert .Net/C#/WPF/EF Certifié MCP disponible sur Paris, province et pays limitrophes (enseignement en français uniquement).
    Mon blog : pragmateek.com

  10. #10
    Invité
    Invité(e)
    Par défaut
    Citation Envoyé par Pragmateek Voir le message
    1. Mais donc autant faire au mieux si ça ne coûte pas plus cher.
    2. Le stagiaire ou le débutant voyant "var" va se poser des questions : comme en JS ? dynamique ? variant ?... autant lui faire gagner du temps, ainsi qu'à son tuteur.
    3. Exprimer son intention est fondamental (et pas qu'en programmation), je te donne un autre exemple où il n'y a pas débat :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    var reference1 = 100;
     
    Console.WriteLine("Intention non exprimée, le compilo joue aux devinettes : {0}", 1 / reference1);
     
    double reference2 = 100;
     
    Console.WriteLine("Intention clairement exprimée : {0}", 1 / reference2);
    Je te laisse découvrir le résultat.
    Mickael, je suis d'accord avec toi qu'il faut exprimer clairement son intention sur le type d'une variable.

    Après, pour l'exemple que tu mentionnes, ce n'est pas compliqué lorsqu'on connait le fonctionnement du compilateur, et la doc MSDN permet de connaître parfaitement ces comportements qui sont des conventions.
    Par exemple, pour le "var reference=100;" c'est un "int" d'une manière évidente et donc la division va renvoyer 0 car 0.01 tronqué sans décimales (comportement que tout développeur .NET est censé connaître). Ce sont de toutes façons des choses de base qu'il faut savoir et donc apprendre.

    Ensuite, il y a d'autres conventions à connaître :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
     
    var v0 = 5; //var=int
    var v1 = 5.0; // var=double
    var v2 = 5F; //var = float
    var v3 = 5L; //var = long
    var v4 = 5m; //var = decimal
    var v5 = '5'; //var = char
    Après, c'est sûr qu'il n'y a aucun intérêt à faire :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
     
    var v6 = (byte)254;
    var v7 = (short)65000;
    car c'est plus court d'écrire :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
     
    byte v6 = 254;
    short v7 = 65000;
    Autre petit détail : ce n'est pas le compilo qui joue aux devinettes, c'est le stagiaire ignorant... Le compilateur sait toujours ce qu'il faut faire!

    C'est important de bien connaître ces conventions, car justement il faut savoir ce qui se passe quand on fait :
    car le résultat de cela peut surprendre!

  11. #11
    Membre expert
    Avatar de Pragmateek
    Homme Profil pro
    Formateur expert .Net/C#
    Inscrit en
    Mars 2006
    Messages
    2 635
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 37
    Localisation : France, Val de Marne (Île de France)

    Informations professionnelles :
    Activité : Formateur expert .Net/C#
    Secteur : Conseil

    Informations forums :
    Inscription : Mars 2006
    Messages : 2 635
    Points : 3 958
    Points
    3 958
    Par défaut
    Et justement avec un code clair tout le monde, même le débutant pas au fait de toutes les règles, peut le comprendre et le maintenir.
    C'est une question de productivité, et au final c'est la boîte qui est facturée, et donc si on baisse la barrière à l'entrée le client n'aura pas besoin de se payer un dev expérimenté pour décrypter le code.
    Le typage est un outil fondamental pour écrire du code expressif et auto-documenté.

    var est là pour de bonnes raisons, il faut juste éviter d'en abuser.

    A ce propos, d'autres features peuvent être détournées de façon plus constructives comme le bloc using : C# : scope your global state changes with IDisposable and the using statement
    Mais bon là aussi le débat existe parce que c'est plus pointu et donc un terrain plus glissant.
    Formateur expert .Net/C#/WPF/EF Certifié MCP disponible sur Paris, province et pays limitrophes (enseignement en français uniquement).
    Mon blog : pragmateek.com

  12. #12
    Modérateur
    Avatar de DotNetMatt
    Homme Profil pro
    CTO
    Inscrit en
    Février 2010
    Messages
    3 611
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 36
    Localisation : Etats-Unis

    Informations professionnelles :
    Activité : CTO
    Secteur : Finance

    Informations forums :
    Inscription : Février 2010
    Messages : 3 611
    Points : 9 743
    Points
    9 743
    Billets dans le blog
    3
    Par défaut
    Ph_Gr a tout dit

    Sur le point 2 du post #9, je suis d'accord avec toi, ça peut être déroutant pour un débutant, surtout s'il vient du monde C/C++. S'il a déjà fait du VB.NET, il sera moins perdu, puisqu'on peut assimiler le var à Dim.

    Ensuite concernant ton dernier post, ce n'est clairement pas de l'obfuscation de code (heureusement d'ailleurs), c'est du sucre syntaxique, donc totalement transparent. Encore une fois il suffit de laisser son curseur sur la variable pour voir son type, rien de bien sorcier. Sur notre projet nous intégrons aussi bien des juniors que des seniors, et il ne semble pas que cela pose problème. Au début certains sont un peu déroutés mais ce n'est pas un frein à l'embauche de juniors.

    Le seul impact que nous avons eu suite à la décision de généraliser l'utilisation de var est de demander aux architectes d'être plus vigilants lors des revues de code (systématiques) sur son utilisation lorsqu'il y a des calculs (dans cette situation, on force les développeurs à expliciter les types via la notation raccourcie mentionnée par Ph_Gr, afin d'éviter les confusions). Il y a bien sûr des exceptions, où l'utilisation de var est impossible (ex. initialiser une variable à null avant un bloc de code type switch ou if), donc là on autorise à spécifier le type avant le nom de la nouvelle variable.

    De notre côté, le principal argument qui nous a motivé à faire ce choix, c'est qu'il offre un certain confort de lecture par rapport à la notation classique, surtout sur les types génériques que nous utilisons abondamment.

    D'ailleurs ce post démontre bien qu'il s'agit juste de sucre syntaxique : Will using 'var' affect performance?. RichardOD a compilé ce code :
    Code C# : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    static void Main(string[] args)
    {
    	var x = "hello";
    	string y = "hello again!";
    	Console.WriteLine(x);
    	Console.WriteLine(y);
    }
    Une fois décompilé, il obtient ceci :
    Code C# : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    private static void Main(string[] args)
    {
    	string x = "hello";
    	string y = "hello again!";
    	Console.WriteLine(x);
    	Console.WriteLine(y);
    }
    Et en-dessous, le post de Rob démontre que l'IL généré est le même, qu'on utilise var ou le type... Donc ce n'est pas une affaire de bonne ou mauvaise pratique, cela n'aura pas non plus d'impact sur les performances ou la productivité, à chacun de choisir ce qu'il préfère.
    Less Is More
    Pensez à utiliser les boutons , et les balises code
    Desole pour l'absence d'accents, clavier US oblige
    Celui qui pense qu'un professionnel coute cher n'a aucune idee de ce que peut lui couter un incompetent.

  13. #13
    Membre expert
    Avatar de Pragmateek
    Homme Profil pro
    Formateur expert .Net/C#
    Inscrit en
    Mars 2006
    Messages
    2 635
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 37
    Localisation : France, Val de Marne (Île de France)

    Informations professionnelles :
    Activité : Formateur expert .Net/C#
    Secteur : Conseil

    Informations forums :
    Inscription : Mars 2006
    Messages : 2 635
    Points : 3 958
    Points
    3 958
    Par défaut
    Ensuite concernant ton dernier post, ce n'est clairement pas de l'obfuscation de code (heureusement d'ailleurs), c'est du sucre syntaxique, donc totalement transparent. Encore une fois il suffit de laisser son curseur sur la variable pour voir son type, rien de bien sorcier. Sur notre projet nous intégrons aussi bien des juniors que des seniors, et il ne semble pas que cela pose problème. Au début certains sont un peu déroutés mais ce n'est pas un frein à l'embauche de juniors.
    Obfuscation et sucre syntaxique sont souvent les 2 faces d'une même médaille.
    Par exemple j'aime écrire :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    event EventHandler<EventArgs> SomethingHappened = delegate { }
    Parce que ça évite de checker la nullité et de devoir gérer la race-condition subtile quand tu invoques le delegate.
    C'est du beau sucre syntaxique mais je reconnais que ça obfusque un peu le code pour quelqu'un qui débarque.

    Le seul impact que nous avons eu suite à la décision de généraliser l'utilisation de var est de demander aux architectes d'être plus vigilants lors des revues de code (systématiques) sur son utilisation lorsqu'il y a des calculs (dans cette situation, on force les développeurs à expliciter les types via la notation raccourcie mentionnée par Ph_Gr, afin d'éviter les confusions). Il y a bien sûr des exceptions, où l'utilisation de var est impossible (ex. initialiser une variable à null avant un bloc de code type switch ou if), donc là on autorise à spécifier le type avant le nom de la nouvelle variable.

    De notre côté, le principal argument qui nous a motivé à faire ce choix, c'est qu'il offre un certain confort de lecture par rapport à la notation classique, surtout sur les types génériques que nous utilisons abondamment.
    J'imagine que vous aviez de bonnes raisons de le faire donc je ne jugerai pas.

    En revanche un des critères de qualité d'une base de code est la cohérence.
    C'est pour ça que je préconise d'utiliser "" au lieu de string.Empty parce que ce dernier n'est pas utilisable partout en raison de sa non-constance.
    De même var vous oblige à ne pas avoir une cohérence syntaxique :
    - que ce soit pour être plus lisible à certains endroits
    - ou bien par obligation dans le cas où en effet vous affectez null.
    Après il ne faut pas être dogmatique (je suis le 1er à proner plus de pragmatisme dans le développement logiciel et l'IT en général ) et bien sûr que des pros comme vous maitrisent parfaitement leur base de code et que c'est donc un détail.
    Mais dans le cas général ce sont des points à considérer parce que pour les bases de code sur lesquelles passent plus de développeurs que d'automobilistes sur une aire d'autoroute le 15/08 (on va éviter les métaphores graveleuses ) ça peut faire une grosse différence (softs développés en interne par les intercontrats des SSII typiquement).
    Formateur expert .Net/C#/WPF/EF Certifié MCP disponible sur Paris, province et pays limitrophes (enseignement en français uniquement).
    Mon blog : pragmateek.com

  14. #14
    Invité
    Invité(e)
    Par défaut
    Citation Envoyé par Pragmateek Voir le message
    C'est pour ça que je préconise d'utiliser "" au lieu de string.Empty parce que ce dernier n'est pas utilisable partout en raison de sa non-constance.
    Ah bon?
    Je pensais plutôt l'inverse car à chaque fois que l'on déclare "", on déclare une nouvelle référence pour la chaîne vide, alors qu'avec String.Empty on réutilise la même référence.
    Peux-tu nous en dire plus concernant cette "non constance"? Je n'ai rien trouvé concernant cela en décompilant l'assemblage mscorlib... A moins que ce ne soit le "__DynamicallyInvocable"?... D'ailleurs, en interne dans les assemblages du Framework, "string.Empty" est utilisé à énormément d'endroits...

  15. #15
    Membre expert
    Avatar de Pragmateek
    Homme Profil pro
    Formateur expert .Net/C#
    Inscrit en
    Mars 2006
    Messages
    2 635
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 37
    Localisation : France, Val de Marne (Île de France)

    Informations professionnelles :
    Activité : Formateur expert .Net/C#
    Secteur : Conseil

    Informations forums :
    Inscription : Mars 2006
    Messages : 2 635
    Points : 3 958
    Points
    3 958
    Par défaut
    Je pensais plutôt l'inverse car à chaque fois que l'on déclare "", on déclare une nouvelle référence pour la chaîne vide, alors qu'avec String.Empty on réutilise la même référence.
    Légende urbaine : d'une part l'interning de la CLR empêche ce phénomène, et même au niveau du code natif généré c'est strictement identique.

    Peux-tu nous en dire plus concernant cette "non constance"?
    Le langage C# exige que certaines valeurs soient constantes, e.g. les valeurs des paramètres par défaut :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    void F(string s = string.Empty) // KO
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    void F(string s = "") // OK
    Idem pour les sélecteurs dans les switch et les valeurs d'attributs.

    Donc si dans ton code tu utilises string.Empty tu seras obligé de le faire cohabiter avec "" => incohérence.
    Et même sans ce problème, "" est plus clair, expressif et concis, string.Empty c'est clairement de l'overengineering.
    Et je sais de quoi je parle, j'avais moi même à une époque développé des méthodes d'extension IsNull/IsNotNull pour écrire :
    plutôt que :
    Sexy, fluent... mais bon pour pas gagner grand chose, et surtout rendre le code moins standard ; donc je ne vais pas lancer la pierre.
    "" ça parle à tous les développeurs du monde, string.Empty non et certains se sont posé des questions, ont fait des hypothèses, ont créé des légendes urbaines, bref ça a brouillé les cartes.

    D'ailleurs, en interne dans les assemblages du Framework, "string.Empty" est utilisé à énormément d'endroits...
    Malheureusement Microsoft est rarement la référence quand il s'agit de faire un bon usage de ses propres technologies : un exemple parmi d'autres est une démo "pet shop" il y a quelques années qui accumulait les mauvaises pratiques.
    Pas très sérieux quand on veut faire de la pub pour une techno. :/
    Comme on dit les cordonniers sont souvent les plus mal chaussés.
    Formateur expert .Net/C#/WPF/EF Certifié MCP disponible sur Paris, province et pays limitrophes (enseignement en français uniquement).
    Mon blog : pragmateek.com

  16. #16
    Invité
    Invité(e)
    Par défaut
    Bonjour,
    Citation Envoyé par Pragmateek Voir le message
    Légende urbaine : d'une part l'interning de la CLR empêche ce phénomène, et même au niveau du code natif généré c'est strictement identique.

    Le langage C# exige que certaines valeurs soient constantes, e.g. les valeurs des paramètres par défaut :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    void F(string s = string.Empty) // KO
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    void F(string s = "") // OK
    Idem pour les sélecteurs dans les switch et les valeurs d'attributs...
    Ah oui, je comprend ce que tu voulais dire, et effectivement : d'une part "String.Empty" n'est pas déclaré en constant mais en static readonly, et d'autre part la chaine vide est bien détectée comme constante dans les paramètres optionnels des fonctions ainsi que dans les switch (et pas seulement la chaîne vide d'ailleurs).
    C'est évident maintenant que tu mentionnes ces arguments.
    Du coup, je m'aperçois que j'avais une vision erronée du système de création des chaînes de caractères.
    Eh bien merci de m'avoir ouvert les yeux la dessus.

    Citation Envoyé par Pragmateek Voir le message
    Malheureusement Microsoft est rarement la référence quand il s'agit de faire un bon usage de ses propres technologies : un exemple parmi d'autres est une démo "pet shop" il y a quelques années qui accumulait les mauvaises pratiques.
    Pas très sérieux quand on veut faire de la pub pour une techno. :/
    Comme on dit les cordonniers sont souvent les plus mal chaussés.

  17. #17
    Membre éprouvé
    Homme Profil pro
    Architecte technique
    Inscrit en
    Septembre 2005
    Messages
    462
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Maine et Loire (Pays de la Loire)

    Informations professionnelles :
    Activité : Architecte technique
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Septembre 2005
    Messages : 462
    Points : 1 056
    Points
    1 056
    Par défaut
    Citation Envoyé par Pragmateek Voir le message
    ...
    Explication convaincante.

    Merci

  18. #18
    Membre expert
    Avatar de Pragmateek
    Homme Profil pro
    Formateur expert .Net/C#
    Inscrit en
    Mars 2006
    Messages
    2 635
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 37
    Localisation : France, Val de Marne (Île de France)

    Informations professionnelles :
    Activité : Formateur expert .Net/C#
    Secteur : Conseil

    Informations forums :
    Inscription : Mars 2006
    Messages : 2 635
    Points : 3 958
    Points
    3 958
    Par défaut
    Tout le plaisir est pour moi.
    Formateur expert .Net/C#/WPF/EF Certifié MCP disponible sur Paris, province et pays limitrophes (enseignement en français uniquement).
    Mon blog : pragmateek.com

  19. #19
    Membre actif
    Homme Profil pro
    Développeur .NET
    Inscrit en
    Juin 2011
    Messages
    95
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Nord (Nord Pas de Calais)

    Informations professionnelles :
    Activité : Développeur .NET
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Juin 2011
    Messages : 95
    Points : 264
    Points
    264
    Par défaut
    En complément de cette belle analyse sur le String.Empty je me suis posé aussi la question, car j'utilisais très souvent cette valeur.

    Donc d'après ce que je comprend, c'est pour l'utiliser avec du code non managé que cette valeur n'est pas une constante mais un static readonly...

    Mais dans ce cas là, pouvez vous me dire la différence entre const et static readonly? Car une constante est forcément static et readonly non? Il doit y avoir une subtilité qui m'échappe.

  20. #20
    Modérateur
    Avatar de DotNetMatt
    Homme Profil pro
    CTO
    Inscrit en
    Février 2010
    Messages
    3 611
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 36
    Localisation : Etats-Unis

    Informations professionnelles :
    Activité : CTO
    Secteur : Finance

    Informations forums :
    Inscription : Février 2010
    Messages : 3 611
    Points : 9 743
    Points
    9 743
    Billets dans le blog
    3
    Par défaut
    Pragmateek, effectivement il ne faut pas non plus être dogmatique. En tout cas c'est intéressant d'avoir d'autres points de vue sur ce genre de sujet

    Je rebondis sur string.Empty, dans StyleCop la règle SA1122: UseStringEmptyForEmptyStrings oblige par défaut à utiliser string.Empty plutôt que "". Au final on est donc orientés vers l'utilisation de string.Empty. On peut bien sûr s'en passer, mais il faut déjà savoir qu'une telle règle existe pour pouvoir la désactiver... Et le fait que cette règle soit active par défaut peut induire dans l'esprit des utilisateurs que string.Empty est la "norme", alors qu'elle ne l'est pas forcément.
    Less Is More
    Pensez à utiliser les boutons , et les balises code
    Desole pour l'absence d'accents, clavier US oblige
    Celui qui pense qu'un professionnel coute cher n'a aucune idee de ce que peut lui couter un incompetent.

Partager

Partager
  • Envoyer la discussion sur Viadeo
  • Envoyer la discussion sur Twitter
  • Envoyer la discussion sur Google
  • Envoyer la discussion sur Facebook
  • Envoyer la discussion sur Digg
  • Envoyer la discussion sur Delicious
  • Envoyer la discussion sur MySpace
  • Envoyer la discussion sur Yahoo