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 :

Commande c# non fonctionnelle, parfois


Sujet :

C#

  1. #21
    Membre Expert
    Homme Profil pro
    edi
    Inscrit en
    Juin 2007
    Messages
    941
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Gironde (Aquitaine)

    Informations professionnelles :
    Activité : edi

    Informations forums :
    Inscription : Juin 2007
    Messages : 941
    Par défaut
    À quel quel genre d'optimisation fais-tu allusion ? Tu parles bien de la chaîne qui constitue le format passé en paramètre à string.Format ? Pourquoi penses-tu que ce qui est fait avec cette chaîne ne pourrait pas être fait avec les parties littérale de la chaîne interpolée ? Dans le pire des cas une première passe pourrait transformer une chaîne interpolée en appel string.Format et on serait égalité. Et pour le peu que je sais, les littéraux de chaîne dans le code sont simplement stockés sous forme de constantes dans l'assembly, je ne vois pas ce qui change d'un cas à l'autre.

    Tu as des références que je pourrais consulter ?

  2. #22
    Expert confirmé
    Avatar de popo
    Homme Profil pro
    Analyste programmeur Delphi / C#
    Inscrit en
    Mars 2005
    Messages
    3 006
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Rhône (Rhône Alpes)

    Informations professionnelles :
    Activité : Analyste programmeur Delphi / C#
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Mars 2005
    Messages : 3 006
    Par défaut
    Pas besoin de référence pour comprendre que dans la chaine "Welcome back dear {0} !", il n'y a qu'une seule constante à stocker.
    Alors que dans la chaine interpolée $"Welcome back dear {customerName} !" il y en deux : "Welcome back dear " et " !".

    De plus, les chaines interpolées ne peuvent être optimisées qu'à partir de C# 10 et UNIQUEMENT si tous les membres sont constants.
    Dans ce cas, et dans uniquement ce cas, le compilateur va parvenir à ne stocker qu'une seule constante.

    Si vraiment, il faut en passer par des références, il suffit de lire la doc de Microsoft.
    https://learn.microsoft.com/fr-fr/do...s/interpolated
    Citation Envoyé par Microsoft
    Le compilateur vérifie si une chaîne interpolée est affectée à un type qui satisfait au modèle de gestionnaire de chaînes interpolé . Un gestionnaire de chaîne interpolée est un type qui convertit la chaîne interpolée en chaîne de résultat. Lorsqu’une chaîne interpolée a le type string, elle est traitée par System.Runtime.CompilerServices.DefaultInterpolatedStringHandler
    Pour résumer :
    La chaine "Welcome back dear {0} !" sera directement traitée comme une constante par le compilateur. C'est optimisé.
    La chaine $"Welcome back dear {customerName} !" nécessitera un traitement supplémentaire par le compilateur pour savoir comment la traiter. Ce n'est optimisé qu'à partir de C# 10 et à la condition que customerName soit une constante.

  3. #23
    Membre Expert
    Homme Profil pro
    edi
    Inscrit en
    Juin 2007
    Messages
    941
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Gironde (Aquitaine)

    Informations professionnelles :
    Activité : edi

    Informations forums :
    Inscription : Juin 2007
    Messages : 941
    Par défaut
    De façon générale, je reste extrêmement dubitatif sur toutes ces affirmations. Mais je vois bien que, de toute façon, on n'arrivera pas à s'entendre sur ce sujet. Au moins ça m'aura pousser à chercher plus d'informations et permis de mieux connaître mon outil de travail, alors ce n'est pas non plus du temps perdu.

    Bonne continuation.

  4. #24
    Expert confirmé
    Avatar de popo
    Homme Profil pro
    Analyste programmeur Delphi / C#
    Inscrit en
    Mars 2005
    Messages
    3 006
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Rhône (Rhône Alpes)

    Informations professionnelles :
    Activité : Analyste programmeur Delphi / C#
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Mars 2005
    Messages : 3 006
    Par défaut
    Comme précisé dans mon dernier message, ces affirmations sont écrites noires sur blancs dans la documentation de Microsoft.
    Le lien qui pointe spécifiquement sur la compilation des chaines interpolées dans la page déjà mentionnée :
    https://learn.microsoft.com/fr-fr/do...olated-strings

    C'est compréhensible d'être dubitatif quand c'est moi qui fait ces affirmations.
    Cela ne l'est pas quand ces affirmations proviennent directement de la documentation officielle.

    Si te ne crois même pas ce que marque Microsoft dans sa documentation officielle, il y a en effet peu de chance qu'on arrive à s'entendre.

    Pour ma part, la principale raison pour laquelle j'évite les chaines interpolée est qu'elle ne me sont d'aucune utilité dans la mesure où la plupart des chaines que j'affiche doivent être traduites dans 3 langues différentes et sont donc placée dans des fichiers de ressources. Le seul cas où je pourrais éventuellement les utiliser, c'est dans les logs.

  5. #25
    Membre Expert
    Homme Profil pro
    edi
    Inscrit en
    Juin 2007
    Messages
    941
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Gironde (Aquitaine)

    Informations professionnelles :
    Activité : edi

    Informations forums :
    Inscription : Juin 2007
    Messages : 941
    Par défaut
    Citation Envoyé par popo Voir le message
    Pas besoin de référence pour comprendre que dans la chaine "Welcome back dear {0} !", il n'y a qu'une seule constante à stocker.
    Alors que dans la chaine interpolée $"Welcome back dear {customerName} !" il y en deux : "Welcome back dear " et " !".
    Ce n'est même pas certain. Avant l'introduction du handler pattern, le comportement par défaut (c'est-à-dire faute d'une meilleure approche), consistait à remplacer les chaînes interpolées
    par un appel à string.Format, donc on est sur un comportement équivalent. C'est bien dans la doc.

    Today, string interpolation mainly lowers down to a call to string.Format.
    Citation Envoyé par popo Voir le message
    De plus, les chaines interpolées ne peuvent être optimisées qu'à partir de C# 10 et UNIQUEMENT si tous les membres sont constants.
    Dans ce cas, et dans uniquement ce cas, le compilateur va parvenir à ne stocker qu'une seule constante.
    Le comportement du compilateur est un peu plus élaboré que ça, comme le précise Stephen Toub, développeur Microsoft, dans un article sur le blog Microsoft. Selon le contexte, il peut créer une constante, utiliser string.Concat, string.Format, et ce même avant l'introduction du handler pattern avec C# 10.

    Citation Envoyé par popo Voir le message
    Pour résumer :
    La chaine "Welcome back dear {0} !" sera directement traitée comme une constante par le compilateur. C'est optimisé.
    Optimisé par rapport à quoi ? Le temps d'exécution ? L'empreinte mémoire ? Le nombre d'allocations ou leur place (stack vs heap) ? Optimisé en comparaison avec quelle alternative ? Si ton seul argument est qu'il n'y aura qu'une seule constante au lieu de deux ou trois, ça me paraît un peu léger. Par ailleurs, le document de spécifications indique clairement que string.Format n'est pas considéré comme une solution optimale, raison pour laquelle une autre approche a été recherchée :

    Today, string interpolation mainly lowers down to a call to string.Format. This, while general purpose, can be inefficient for a number of reasons:

    It boxes any struct arguments, unless the runtime has happened to introduce an overload of string.Format that takes exactly the correct types of arguments in exactly the correct order.
    This ordering is why the runtime is hesitant to introduce generic versions of the method, as it would lead to combinatoric explosion of generic instantiations of a very common method.
    It has to allocate an array for the arguments in most cases.
    There is no opportunity to avoid instantiating the instance if it's not needed. Logging frameworks, for example, will recommend avoiding string interpolation because it will cause a string to be realized that may not be needed, depending on the current log-level of the application.
    It can never use Span or other ref struct types today, because ref structs are not allowed as generic type parameters, meaning that if a user wants to avoid copying to intermediate locations they have to manually format strings.
    Citation Envoyé par popo Voir le message
    La chaine $"Welcome back dear {customerName} !" nécessitera un traitement supplémentaire par le compilateur pour savoir comment la traiter. Ce n'est optimisé qu'à partir de C# 10 et à la condition que customerName soit une constante.
    Là encore il faudrait préciser de quelle optimisation il s'agit. Et l'article de Toub explique clairement que cette affirmation est fausse.

    Je ne dis pas pour autant que string.Format est obsolète, l'interpolation n'est disponible que dans des fichiers de code et l'utilisation de formats issus d'un fichier de ressources, comme l'exemple que tu donnes, est un cas d'usage. Mais je suis en désaccord avec l'analyse que tu fais des chaînes interpolées.

  6. #26
    Expert confirmé
    Avatar de popo
    Homme Profil pro
    Analyste programmeur Delphi / C#
    Inscrit en
    Mars 2005
    Messages
    3 006
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Rhône (Rhône Alpes)

    Informations professionnelles :
    Activité : Analyste programmeur Delphi / C#
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Mars 2005
    Messages : 3 006
    Par défaut
    Citation Envoyé par Noxen Voir le message
    Ce n'est même pas certain. Avant l'introduction du handler pattern, le comportement par défaut (c'est-à-dire faute d'une meilleure approche), consistait à remplacer les chaînes interpolées par un appel à string.Format
    C'est précisément ce que j'ai dit.

    Citation Envoyé par Noxen Voir le message
    donc on est sur un comportement équivalent. C'est bien dans la doc.
    On est sur un équivalent en exécution, pas en compilation.
    Décidemment, tu as du mal à faire la différence.


    Citation Envoyé par Noxen Voir le message
    Le comportement du compilateur est un peu plus élaboré que ça, comme le précise Stephen Toub, développeur Microsoft, dans un article sur le blog Microsoft. Selon le contexte, il peut créer une constante, utiliser string.Concat, string.Format, et ce même avant l'introduction du handler pattern avec C# 10.
    Je te suggère de relire cet article attentivement.
    Il est clairement spécifié que c'est parce que Greeting et Name sont des litéraux (donc des constantes) que le compilateur créé un littéral.
    Bref, exactement la même que ce que j'ai dit : "Dans ce cas, et dans uniquement ce cas, le compilateur va parvenir à ne stocker qu'une seule constante."


    Citation Envoyé par Noxen Voir le message
    Optimisé par rapport à quoi ? Le temps d'exécution ? L'empreinte mémoire ? Le nombre d'allocations ou leur place (stack vs heap) ? Optimisé en comparaison avec quelle alternative ? Si ton seul argument est qu'il n'y aura qu'une seule constante au lieu de deux ou trois, ça me paraît un peu léger.
    Une constante qui n'a pas besoin d'être analysée, c'est optimisé par rapport au travail supplémentaire que doit fournir le compilateur pour analyser la chaine interpolée et la transformer soit en constante dans le meilleur des cas, soit en appel string.Concat, soit en string.format, etc.
    L'argument du nombre, je l'ai mis car il est simple à comprendre.

    Citation Envoyé par Noxen Voir le message
    Par ailleurs, le document de spécifications indique clairement que string.Format n'est pas considéré comme une solution optimale, raison pour laquelle une autre approche a été recherchée :
    Là aussi, je te suggères de relire attentivement cet article.
    Il est dit que faire un string.Format sur un chaine interpolée n'est pas optimal.
    Ce qui est logique puisque string.Format fonctionne avec des constantes numériques et qu'il faut donc analyser la chaine interpolée pour déduire les index et passer les valeurs.
    L'apparition du InterpolatedStringHandler a permis de se passer de ce traitement supplémentaire.
    Edit : Mais il y a quand même un traitement pour déterminer sur quoi appeler AppendLiteral et sur quoi Appeler AppendFormatted.


    Citation Envoyé par Noxen Voir le message
    Là encore il faudrait préciser de quelle optimisation il s'agit. Et l'article de Toub explique clairement que cette affirmation est fausse.
    Et pourtant l'article précise :
    The C# compiler is free to generate whatever code it deems best for an interpolated string, as long as it ends up producing the same result, and today it has multiple mechanisms it might employ, depending on the situation
    the C# compiler can see that all portions of the interpolated string are string literals, and it can emit this into IL as if it had been written as a single string literal:
    The C# compiler can see that all of the format items are filled with strings, so it can generate a call to String.Concat:
    For example, if you were to write...he C# compiler will emit code similar to the string.Format call we saw earlier
    Il y a clairement une analyse (donc un un traitement supplémentaire) pour savoir comment traiter la chaine interpolée selon la situation.
    Prétendre que c'est faux, c'est carrément de la mauvaise foi !

    Citation Envoyé par Noxen Voir le message
    Je ne dis pas pour autant que string.Format est obsolète, l'interpolation n'est disponible que dans des fichiers de code et l'utilisation de formats issus d'un fichier de ressources, comme l'exemple que tu donnes, est un cas d'usage. Mais je suis en désaccord avec l'analyse que tu fais des chaînes interpolées.
    Encore une fois ce n'est pas mon analyse, c'est le contenu de la documentation officielle.

  7. #27
    Membre Expert
    Homme Profil pro
    edi
    Inscrit en
    Juin 2007
    Messages
    941
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Gironde (Aquitaine)

    Informations professionnelles :
    Activité : edi

    Informations forums :
    Inscription : Juin 2007
    Messages : 941
    Par défaut
    Ce que tu appelles une optimisation c'est qu'un string.Format est plus simple à analyser par le compilateur qu'une chaîne interpolée ?

  8. #28
    Expert confirmé
    Avatar de popo
    Homme Profil pro
    Analyste programmeur Delphi / C#
    Inscrit en
    Mars 2005
    Messages
    3 006
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Rhône (Rhône Alpes)

    Informations professionnelles :
    Activité : Analyste programmeur Delphi / C#
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Mars 2005
    Messages : 3 006
    Par défaut
    Pas du tout.

    Ce que je dis n'est ni plus ni moins qu'un résumé de ce que dis la documentation officielle traitant expressément de la compilation des chaines interpolées.
    https://learn.microsoft.com/en-us/do...olated-strings
    Compilation of interpolated strings
    The compiler checks if an interpolated string is assigned to a type that satisfies the interpolated string handler pattern. An interpolated string handler is a type that converts the interpolated string into a result string. When an interpolated string has the type string, it's processed by the System.Runtime.CompilerServices.DefaultInterpolatedStringHandler. For the example of a custom interpolated string handler, see the Write a custom string interpolation handler tutorial. Use of an interpolated string handler is an advanced scenario, typically required for performance reasons.


    One side effect of interpolated string handlers is that a custom handler, including System.Runtime.CompilerServices.DefaultInterpolatedStringHandler, may not evaluate all the interpolation expressions within the interpolated string under all conditions. That means side effects of those expressions may not occur.

    If an interpolated string has the type string, it's typically transformed into a String.Format method call. The compiler can replace String.Format with String.Concat if the analyzed behavior would be equivalent to concatenation.

    If an interpolated string has the type IFormattable or FormattableString, the compiler generates a call to the FormattableStringFactory.Create method.
    Ce texte contient des explications sommaires sur tout ce que doit faire le compilateur pour traiter une chaine interpolée.
    Il contient également une mise en garde sur des cas où la chaine interpolée pourrait introduire un effet secondaire non désiré.
    Il n'est pire aveugle que celui qui ne veut pas voir.

  9. #29
    Membre Expert
    Homme Profil pro
    edi
    Inscrit en
    Juin 2007
    Messages
    941
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Gironde (Aquitaine)

    Informations professionnelles :
    Activité : edi

    Informations forums :
    Inscription : Juin 2007
    Messages : 941
    Par défaut
    Citation Envoyé par popo Voir le message
    Ce texte contient des explications sommaires sur tout ce que doit faire le compilateur pour traiter une chaine interpolée.
    Je ne vois pas en quoi c'est un sujet, ce qui compte c'est l'assembly qui en résulte.
    Ce qu'on appelle compilation se fait en plusieurs étapes :
    - il y a d'abord une phase de pré-traitement, qui va modifier le code source, notamment par les opérations de lowering. Par exemple, les foreach sont remplacés par du code utilisant les énumérateurs (ou une boucle for pour les tableaux) ; c'est aussi dans cette phase que sera évaluée la chaîne interpolée et qu'elle sera remplacée par le code effectif ;
    - puis la génération du code IL à partir du code source transformé.
    Si pendant le pré-traitement la chaîne interpolée est remplacée par string.Format et une constante, alors logiquement le code IL généré sera le même que si ce code était celui-ci dès le départ.

    Citation Envoyé par popo Voir le message
    Il contient également une mise en garde sur des cas où la chaine interpolée pourrait introduire un effet secondaire non désiré.
    À relire. Ce que tu mentionnes concerne les handlers personnalisés, c'est-à-dire pas le DefaultInterpolatedStringHandler du framework et concerne un cas particulier. Il est en effet possible créer un handler qui peut être désactivé à l'exécution. En gros, il faut rajouter au constructeur un paramètre out bool isEnabled et le compilateur rajoutera une structure de contrôle :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    if (isEnabled)
    {
        // appel aux méthodes AppendLitteral et AppendFormatted
    }
    Cela signifie que si isEnabled est false le code dans les expressions interpolées ne sera pas invoqué. C'est un effet recherché, afin de ne pas invoquer le code de build si le résultat ne sera pas utilisé. Une bibliothèque de logging peut profiter de cela pour ne pas fabriquer un message s'il ne sera pas logué parce-qu'il n'est pas d'un niveau suffisant (ex. c'est un warning et le logger ne logge qu'à partir des erreurs). La conséquence est que les éventuels effets de bord associés aux expressions ne seront pas générés non plus. Référence : créer un interpolated string handler personnalisé.

  10. #30
    Expert confirmé
    Avatar de popo
    Homme Profil pro
    Analyste programmeur Delphi / C#
    Inscrit en
    Mars 2005
    Messages
    3 006
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Rhône (Rhône Alpes)

    Informations professionnelles :
    Activité : Analyste programmeur Delphi / C#
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Mars 2005
    Messages : 3 006
    Par défaut
    Citation Envoyé par Noxen Voir le message
    Je ne vois pas en quoi c'est un sujet, ce qui compte c'est l'assembly qui en résulte.
    Ce qu'on appelle compilation se fait en plusieurs étapes :
    - il y a d'abord une phase de pré-traitement, qui va modifier le code source, notamment par les opérations de lowering. Par exemple, les foreach sont remplacés par du code utilisant les énumérateurs (ou une boucle for pour les tableaux) ; c'est aussi dans cette phase que sera évaluée la chaîne interpolée et qu'elle sera remplacée par le code effectif ;
    - puis la génération du code IL à partir du code source transformé.
    Si pendant le pré-traitement la chaîne interpolée est remplacée par string.Format et une constante, alors logiquement le code IL généré sera le même que si ce code était celui-ci dès le départ
    Tu confonds le processus de compilation et le résultat de la compilation.

    Tout est dans le SI
    Oui, le code IL sera sensiblement le même SI j'utilise effectivement String.format.
    Mais, bien qu'une partie de la chaine interpolée devient une constante, customerName reste une variable.
    Cette variable sera toujours évaluées à l'exécution, ce qui empêche l'optimisation complète à la compilation.
    De toute façon, ceci n'est plus vrai depuis C# 10 qui utilise par défaut le DefaultInterpolatedStringHandler et des appels aux méthode AppendLitteral et AppendFormatted.
    Cela produit un code complexe, certes plus efficace en runtime (et encore ça dépend) mais pas optimisable à la compilation.

    La chaine de "Welcome back dear {0} !" est une constante que le compilateur n'essaie pas de transformer.
    D'ailleurs, ce n'est pas parce qu'il y a un "{0}" que je suis obligé de vouloir y faire correspondre une valeur.
    Je peux très bien pour une raison ou une autre vouloir afficher la chaine telle quelle.

    Je le rappelle, il est question de la chaine en elle même. Pas de ce qu'on en fait.
    Edit : La chaine interpolée devra quoi qu'il arrive être transformée, pas la chaine simple même s'il y a un format dedans.


    Citation Envoyé par Noxen Voir le message
    À relire. Ce que tu mentionnes concerne les handlers personnalisés, c'est-à-dire pas le DefaultInterpolatedStringHandler du framework et concerne un cas particulier.
    Après relecture, je persiste à dire qu'il n'est pire aveugle que celui qui ne veut pas voir.
    Apparemment, tu n'a pas vu ceci :
    including System.Runtime.CompilerServices.DefaultInterpolatedStringHandler

  11. #31
    Membre confirmé
    Profil pro
    Inscrit en
    Avril 2009
    Messages
    78
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Avril 2009
    Messages : 78
    Par défaut
    Salut à tous,

    Bon j'ai passé quelques jours de recherche sur le web, sans succès, je désespère, j'essaie tout et surtout rien, je n'essaie même plus de comprendre, j'applique.



    Citation Envoyé par Noxen Voir le message
    Pour compléter la réponse de tatayo, il est possible de combiner l'interpolation de chaîne avec les raw strings pour se passer des caractère d'échappement :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    string arg = $""" -p "{textBox1.Text}" -y "{textBox2.Text}" -z "{comboBox1.Text}" -v "{comboBox2.Text}" -j 0 "{label1.Text}";""";
    J'ai tenté, il y a une erreur.

    Nom : 1.png
Affichages : 100
Taille : 39,6 Ko










    Citation Envoyé par Noxen Voir le message
    Une autre options est d'en faire une liste de chaînes et d'entourer de guillemets si besoin, puis de joindre avec des espaces :
    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
    string[] args =
    {
        "-p",
        textBox1.Text,
        "-y",
        textBox2.Text,
        "-z",
        comboBox1.Text,
        "-v",
         comboBox2.Text,
         "-j",
         "0",
         label1.Text,
         ";"
    }
    .Select(s => s.Contains(" ") ? "\"{s}\"" : s)
    .ToArray();
     
    string argString = string.Join(' ', args);
    Pareil.

    Nom : 2.png
Affichages : 96
Taille : 60,5 Ko

  12. #32
    Expert confirmé
    Avatar de fred1599
    Homme Profil pro
    Lead Dev Python
    Inscrit en
    Juillet 2006
    Messages
    4 152
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Meurthe et Moselle (Lorraine)

    Informations professionnelles :
    Activité : Lead Dev Python
    Secteur : Arts - Culture

    Informations forums :
    Inscription : Juillet 2006
    Messages : 4 152
    Par défaut
    Tente ça

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    string arg = $" -p \"{textBox1.Text}\" -y \"{textBox2.Text}\" -z \"{comboBox1.Text}\" -v \"{comboBox2.Text}\" -j 0 \"{label1.Text}\"

  13. #33
    Membre Expert
    Homme Profil pro
    edi
    Inscrit en
    Juin 2007
    Messages
    941
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Gironde (Aquitaine)

    Informations professionnelles :
    Activité : edi

    Informations forums :
    Inscription : Juin 2007
    Messages : 941
    Par défaut
    Pour la première erreur, c'est la version du langage qui est en cause, comme l'indique l'erreur, les raw strings ne sont pas disponibles dans celle que tu utilises. La correction proposée par fred1599 devrait fonctionner.

    Pour la deuxième c'est ma faute. Ça aurait fonctionné si on avait directement assignée à une variable de type string[]. On l'occurrence on passe le résultat de l'expression à une méthode d'extension (Select) qui prend en paramètre un IEnumerable<string>, du coup il manque d'informations pour valider l'expression. Pour corriger, on peut soit faire l'assignation en deux fois (un tableau avec les valeurs d'origine puis un avec les valeurs finales), soit rajouter new[] devant l'expression pour lever l'ambiguïté :
    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
    string[] args = new[] // la correction est ici
    {
    	"-p",
    	textBox1.Text,
    	"-y",
    	textBox2.Text,
    	"-z",
    	comboBox1.Text,
    	"-v",
    	 comboBox2.Text,
    	 "-j",
    	 "0",
    	 label1.Text,
    	 ";"
    }
    .Select(s => s.Contains(" ") ? "\"{s}\"" : s)
    .ToArray();
     
    string argString = string.Join(' ', args);
    Tu fais un projet en Net Framework (c'est-à-dire pas en .Net Core ou .Net 5+) ?

  14. #34
    Membre confirmé
    Profil pro
    Inscrit en
    Avril 2009
    Messages
    78
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Avril 2009
    Messages : 78
    Par défaut
    Salut et merci de vos aides, c'est super cool,

    J'ai suivi ce qu'avait donné fred1599, il y manquait 2 caractères en fin de ligne mais ça semble fonctionner ensuite !

    Merci encore à tous !

    La ligne qui a fonctionné :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    \string arg = $" -p \"{textBox1.Text}\" -y \"{textBox2.Text}\" -z \"{comboBox1.Text}\" -v \"{comboBox2.Text}\" -j 0 \"{label1.Text}\"";

  15. #35
    Membre Expert
    Homme Profil pro
    edi
    Inscrit en
    Juin 2007
    Messages
    941
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Gironde (Aquitaine)

    Informations professionnelles :
    Activité : edi

    Informations forums :
    Inscription : Juin 2007
    Messages : 941
    Par défaut
    Citation Envoyé par popo Voir le message
    Tu confonds le processus de compilation et le résultat de la compilation.
    Je ne confond rien du tout, par contre j'avoue que j'ai beaucoup de mal à déterminer quel aspect tu analyses. C'est bien pour ça que je creuse le sujet.

    Citation Envoyé par popo Voir le message
    Tout est dans le SI
    Oui, le code IL sera sensiblement le même SI j'utilise effectivement String.format.
    "Si", signifie que le compilateur n'a pas trouvé de transformation plus adéquate que string.Format. Si string.Format est vraiment optimal, je ne vois pas pourquoi on s'embêterait à élaborer d'autres approches. Quoi qu'il en soit, mon point est qu'on peut considérer que c'est l'implémentation de référence pour résoudre ce problème.

    Citation Envoyé par popo Voir le message
    Mais, bien qu'une partie de la chaine interpolée devient une constante, customerName reste une variable.
    Cette variable sera toujours évaluées à l'exécution, ce qui empêche l'optimisation complète à la compilation.
    En même temps c'est aussi le cas avec string.Format, le format est connu à la compilation, mais c'est à l'exécution qu'une variable sera évaluée passée à la méthode.

    Citation Envoyé par popo Voir le message
    De toute façon, ceci n'est plus vrai depuis C# 10 qui utilise par défaut le DefaultInterpolatedStringHandler et des appels aux méthode AppendLitteral et AppendFormatted.
    Cela produit un code complexe, certes plus efficace en runtime (et encore ça dépend) mais pas optimisable à la compilation.
    Un constructeur est quelques appels de fonction, ce n'est pas ce que j'appelle un code complexe. En fait de complexité, c'est juste de l'inlining, le compilateur se contente d'écrire un peu de code pour qu'on n'aie pas à le faire nous-même. Par ailleurs, si on crée un tableau pour le passer a string.Format, que ce soit explicitement ou implicitement parce-qu'on a plus de 3 arguments et qu'on appelle la surcharge avec param, ça génère presque autant d'IL qu'une chaîne interpolée. Assez ironiquement, en comparant deux assemblies avec le même contenu, celui utilisant des chaînes interpolées fait 10240 octets, contre 10752 pour celui utilisant string.Format. Ceci-dit, on ne peut pas parler de différence significative sans parler du contexte dans lequel cette différence se présente. Et encore une fois, tu parles d'optimisation, sans préciser en quoi elle consiste.

    Citation Envoyé par popo Voir le message
    La chaine de "Welcome back dear {0} !" est une constante que le compilateur n'essaie pas de transformer.
    Ce n'est pas vraiment la question.

    Citation Envoyé par popo Voir le message
    D'ailleurs, ce n'est pas parce qu'il y a un "{0}" que je suis obligé de vouloir y faire correspondre une valeur.
    Dans son emploi avec string.Format, si, autrement tu auras une exception.

    Citation Envoyé par popo Voir le message
    Je peux très bien pour une raison ou une autre vouloir afficher la chaine telle quelle.
    Tu essaies de décontextualiser le sujet. On parle d'une situation où on veut produire une chaîne construite à partir de valeurs au runtime, sinon on n'aurait pas cette conversation.

    Citation Envoyé par popo Voir le message
    Je le rappelle, il est question de la chaine en elle même. Pas de ce qu'on en fait.
    Edit : La chaine interpolée devra quoi qu'il arrive être transformée, pas la chaine simple même s'il y a un format dedans.
    Il est totalement question de ce qu'on va faire de la chaîne. On n'utiliserait pas une chaîne interpolée (ni d'ailleurs un string.Format) si on ne cherchait pas à créer une nouvelle chaîne à partir de valeurs à l'exécution.

    Citation Envoyé par popo Voir le message
    Après relecture, je persiste à dire qu'il n'est pire aveugle que celui qui ne veut pas voir.
    Apparemment, tu n'a pas vu ceci :
    including System.Runtime.CompilerServices.DefaultInterpolatedStringHandler
    Ok, celui-là je suis passé à côté à la relecture. Je ne sais pas par contre à quoi ça correspond, DefaultInterpolatedStringHandler n'implémente pas le pattern isEnabled. Ce passage est un peu bizarre aussi, les deux paragraphes qui l'encadrent sont contradictoires (l'un dit que DefaultInterpolatedStringHandler, l'autre que c'est string.Format).

  16. #36
    Expert confirmé
    Avatar de popo
    Homme Profil pro
    Analyste programmeur Delphi / C#
    Inscrit en
    Mars 2005
    Messages
    3 006
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Rhône (Rhône Alpes)

    Informations professionnelles :
    Activité : Analyste programmeur Delphi / C#
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Mars 2005
    Messages : 3 006
    Par défaut
    Citation Envoyé par Noxen Voir le message
    Je ne confond rien du tout, par contre j'avoue que j'ai beaucoup de mal à déterminer quel aspect tu analyses. C'est bien pour ça que je creuse le sujet.
    Cela fait plusieurs fois que je le répète, l'aspect dont il est question depuis le départ est l'optimisation des chaines à la compilation.


    Citation Envoyé par Noxen Voir le message
    "Si", signifie que le compilateur n'a pas trouvé de transformation plus adéquate que string.Format. Si string.Format est vraiment optimal, je ne vois pas pourquoi on s'embêterait à élaborer d'autres approches.
    Avant C# 10, la chaine interpolée était transformée en string.Format et l'article que tu as toi même mentionné explique en long en large et en travers pourquoi et comment ce mécanisme a changé.


    Citation Envoyé par Noxen Voir le message
    Quoi qu'il en soit, mon point est qu'on peut considérer que c'est l'implémentation de référence pour résoudre ce problème.
    Et bien, ce n'est tout bonnement plus le cas depuis C# 10.
    Encore une fois, c'est dans l'article que tu as toi même cité.


    Citation Envoyé par Noxen Voir le message
    En même temps c'est aussi le cas avec string.Format, le format est connu à la compilation, mais c'est à l'exécution qu'une variable sera évaluée passée à la méthode.
    Je le répète, il est question de l'optimisation des chaines.
    Avec une chaine interpolée, il n'y a pas d'autres choix que de passer par une mécanique qui devra attendre l'exécution pour connaitre la valeur.
    La chaine de format est un simple chaine et c'est le développeur qui choisi de l'utiliser avec string.Format.
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    Console.WriteLine("Exemple de chaines de format >");
     
    // Cette chaine est constante, le compilateur peut l'optimiser
    string format = "Aujourd'hui : {0:yyyy-MM-dd}";
     
    // Ici, la chaine est utilisée sans string.Format
    Console.WriteLine(format);
     
    // Ici, c'est le développeur qui a volontairement choisi de passer par string.Format
    Console.WriteLine(string.Format(format, DateTime.Now));

    Citation Envoyé par Noxen Voir le message
    Un constructeur est quelques appels de fonction, ce n'est pas ce que j'appelle un code complexe. En fait de complexité, c'est juste de l'inlining, le compilateur se contente d'écrire un peu de code pour qu'on n'aie pas à le faire nous-même. Par ailleurs, si on crée un tableau pour le passer a string.Format, que ce soit explicitement ou implicitement parce-qu'on a plus de 3 arguments et qu'on appelle la surcharge avec param, ça génère presque autant d'IL qu'une chaîne interpolée.
    Le code C# n'est pas si complexe, en IL c'est plus compliqué.
    Et de toute manière même si le généré par le compilateur n'était pas très complexe, il le sera toujours en comparaison de la simple constante que représente la chaine de format.
    Et encore une fois, la chaine de format est un simple chaine et c'est le développeur qui choisi de l'utiliser avec string.Format.


    Citation Envoyé par Noxen Voir le message
    Assez ironiquement, en comparant deux assemblies avec le même contenu, celui utilisant des chaînes interpolées fait 10240 octets, contre 10752 pour celui utilisant string.Format. Ceci-dit, on ne peut pas parler de différence significative sans parler du contexte dans lequel cette différence se présente.
    Idem, la chaine de format est un simple chaine et c'est le développeur qui choisi de l'utiliser avec string.Format.

    Citation Envoyé par Noxen Voir le message
    Et encore une fois, tu parles d'optimisation, sans préciser en quoi elle consiste.
    Je ne fais que ça.
    J'ai essayé avec des phrases courtes.
    J'ai essayé avec de longues explications.
    Je vais une ultime fois essayer de le dire simplement :
    La chaine de format est une constante, elle est considéré comme telle par le compilateur qui n'en garde qu'une seule référence, et c'est le développeur qui choisi de l'utiliser avec string.Format.
    La chaine interpolée aura toujours une partie variable que le compilateur ne pourra, par définition, jamais connaitre et donc jamais optimiser.

    Citation Envoyé par Noxen Voir le message
    Ce n'est pas vraiment la question.
    Si, justement.
    C'est la toute la question lorsqu'on parle d'optimisation de chaine à la compilation.


    Citation Envoyé par Noxen Voir le message
    Dans son emploi avec string.Format, si, autrement tu auras une exception.
    Tu essaies de décontextualiser le sujet. On parle d'une situation où on veut produire une chaîne construite à partir de valeurs au runtime, sinon on n'aurait pas cette conversation.
    Il est totalement question de ce qu'on va faire de la chaîne. On n'utiliserait pas une chaîne interpolée (ni d'ailleurs un string.Format) si on ne cherchait pas à créer une nouvelle chaîne à partir de valeurs à l'exécution.
    Non seulement, tu ne veux pas voir, mais en plus, tu as la mémoire courte.
    C'est toi qui a dérivé du sujet initial en parlant de l'optimisation de chaine, le 14/01/2025, à 14h44.



    Citation Envoyé par Noxen Voir le message
    Je ne sais pas par contre à quoi ça correspond, DefaultInterpolatedStringHandler n'implémente pas le pattern isEnabled.
    C'est parce que tu as fait d'un cas spécifique, une généralité.
    L'article que tu as toi même mentionné montre la création d'un TryWriteInterpolatedStringHandler qui n'a pas IsEnable.

    Citation Envoyé par Noxen Voir le message
    Ce passage est un peu bizarre aussi, les deux paragraphes qui l'encadrent sont contradictoires (l'un dit que DefaultInterpolatedStringHandler, l'autre que c'est string.Format).
    Il ne sont pas contradictoire, ils sont complémentaires.
    DefaultInterpolatedStringHandler est utilisé par défaut.
    string.Format est utilisé en dernier recours.

  17. #37
    Membre Expert
    Homme Profil pro
    edi
    Inscrit en
    Juin 2007
    Messages
    941
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Gironde (Aquitaine)

    Informations professionnelles :
    Activité : edi

    Informations forums :
    Inscription : Juin 2007
    Messages : 941
    Par défaut
    Tu as tenu compte du fait que les segments qui composent les chaînes interpolés sont stockés une fois et réutilisés ?

    Le code :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    Console.WriteLine($"Player1: {player1.Name}, {player1.Score}");
    Console.WriteLine($"Player2: {player1.Name}, {player1.Score}");
    va stocker uniquement "Player1 :", "Player2: " et "", ".

    L'équivalent avec un format :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    Console.WriteLine(string.Format("Player1: {0}, {1}", player1.Name, player1.Score));
    Console.WriteLine(string.Format("Player2: {0}, {1}", player2.Name, player2.Score));
    va stocker "Player1: {0}, {1}" et "Player2: {0}, {1}".

    Edit: le point que je veux soulever, c'est que si l'on trouve 200 fois, par exemple le code :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    _logger.Log(Status.Error, $"Error ({DateTime.Now}) => an exception was thrown:\n{e.Message}");
    les chaînes "Error (" et ") => an exception was thrown:\n" ne seront stockées dans l'assembly qu'une seule fois et simplement réutilisées sur chaque call site. Bon, après tu as sans doute un problème de DRY , mais c'est un autre sujet.

  18. #38
    Expert confirmé
    Avatar de popo
    Homme Profil pro
    Analyste programmeur Delphi / C#
    Inscrit en
    Mars 2005
    Messages
    3 006
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Rhône (Rhône Alpes)

    Informations professionnelles :
    Activité : Analyste programmeur Delphi / C#
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Mars 2005
    Messages : 3 006
    Par défaut
    Oui, j'en ai tenu compte.
    Je l'ai même signalé dans mon message du 24/01/2025 à 09h07.

    Alors, je te retourne la remarque que tu as faite le 31/01/2025 à 17h30 :
    Si ton argument c'est qu'il va stocker quelques caractères de plus et donc augmenter la taille de quelques octets, ça me paraît un peu léger.
    Surtout si on tient compte que pour tourner, le programme devra utiliser un runtime largement plus gros que quelques octets (presque 100 Mo pour une version x64).

  19. #39
    Membre Expert
    Homme Profil pro
    edi
    Inscrit en
    Juin 2007
    Messages
    941
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Gironde (Aquitaine)

    Informations professionnelles :
    Activité : edi

    Informations forums :
    Inscription : Juin 2007
    Messages : 941
    Par défaut
    Ce n'étais pas un argument, j'essayais simplement de dissiper une incertitude. Comme tu disais que la chaîne qui sert de format était présente une fois et réutilisée au besoin avec string.Format, ça pouvait laisser penser que le comportement des chaînes interpolées était différent en cela que les segments seraient répétés pour chaque call site.

  20. #40
    Expert confirmé
    Homme Profil pro
    Responsable Données
    Inscrit en
    Janvier 2009
    Messages
    5 464
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 51
    Localisation : France, Hérault (Languedoc Roussillon)

    Informations professionnelles :
    Activité : Responsable Données

    Informations forums :
    Inscription : Janvier 2009
    Messages : 5 464
    Par défaut
    Et Beh...
    Je ne pensais pas déclencher une telle discussion en proposant une chaîne interpolée !

    Tatayo.

Discussions similaires

  1. Incrementer type text parfois non fonctionnel
    Par fabulon46 dans le forum Général JavaScript
    Réponses: 8
    Dernier message: 08/04/2014, 12h47
  2. commande non fonctionnel
    Par djdidi2010 dans le forum WinDev
    Réponses: 2
    Dernier message: 07/05/2012, 13h47
  3. Ligne de commande non fonctionnelle en VB.NET
    Par CLeBeR dans le forum VB.NET
    Réponses: 4
    Dernier message: 25/04/2012, 23h38
  4. Update non fonctionnel
    Par kissmytoe dans le forum Access
    Réponses: 7
    Dernier message: 07/03/2006, 18h37
  5. [REPORTS] Order BY non fonctionnel
    Par sdiack dans le forum Reports
    Réponses: 2
    Dernier message: 10/02/2006, 18h10

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