Refléter le nom du paramètre: abus des expressions lambda C # ou brillance syntaxique?


428

Je regarde le composant MvcContrib Grid et je suis fasciné, mais en même temps repoussé, par une astuce syntaxique utilisée dans la syntaxe Grid :

.Attributes(style => "width:100%")

La syntaxe ci-dessus définit l'attribut style du code HTML généré sur width:100%. Maintenant, si vous faites attention, le «style» n'est spécifié nulle part. Il est déduit du nom du paramètre dans l'expression! J'ai dû creuser cela et j'ai trouvé où la «magie» se produisait:

Hash(params Func<object, TValue>[] hash)
{
    foreach (var func in hash)
    {
        Add(func.Method.GetParameters()[0].Name, func(null));
    }
}

Donc, en effet, le code utilise le nom formel de l'heure de compilation des paramètres pour créer le dictionnaire des paires nom-valeur d'attribut. La construction de syntaxe résultante est certes très expressive, mais en même temps très dangereuse.

L'utilisation générale des expressions lambda permet de remplacer les noms utilisés sans effet secondaire. Je vois un exemple dans un livre qui dit que collection.ForEach(book => Fire.Burn(book))je sais que je peux écrire dans mon code collection.ForEach(log => Fire.Burn(log))et cela signifie la même chose . Mais avec la syntaxe de la grille MvcContrib ici, tout d'un coup, je trouve du code qui regarde activement et prend des décisions en fonction des noms que je choisis pour mes variables!

Est-ce donc une pratique courante avec la communauté C # 3.5 / 4.0 et les amoureux des expressions lambda? Ou est-ce un franc-tireur un truc dont je ne devrais pas m'inquiéter?


34
Je dirais que cela semble évident, tant que vous êtes prêt à examiner l'intention du code, plutôt que de simplement analyser la syntaxe. Ce qui, si vous lisez du bon code, est ce que vous devriez faire de toute façon. La syntaxe n'est qu'un véhicule d'intention, et je dirais que c'est du code révélateur d'intention.
Jamie Penney

191
Je viens de demander à Anders (et au reste de l'équipe de conception) ce qu'ils en pensaient. Disons simplement que les résultats ne seraient pas imprimables dans un journal familial.
Eric Lippert

22
Il manque actuellement à C # une syntaxe claire et claire pour les cartes, en particulier les cartes transmises aux fonctions. Divers langages dynamiques (Ruby, Python, JavaScript, ColdFusion 9) ont une syntaxe propre et légère pour cela, dans une certaine mesure ou une autre.
yfeldblum

28
Oh, je pense que cela semble délicieux. Quant à la syntaxe des cartes, oui, ce serait génial si nous pouvions faire de nouveaux {{"Do", "A deer"}, {"Re", "golden sun"} ...} et que le compilateur infère le construction d'une carte, tout comme new [] {1, 2,3} infère la construction d'un tableau int. Nous envisageons ce genre de choses.
Eric Lippert

17
Eric Lippert, je vous respecte énormément, mais je pense que vous et le groupe (y compris Anders, que je respecte FREAKIN 'TREMENDOUSLY) réprimandez trop durement. Comme vous l'admettez, C # n'a pas de syntaxe stricte pour les cartes, et d'autres langs (comme Ruby) en ont d'excellents. Ce gars a trouvé un moyen d'obtenir la syntaxe qu'il voulait. Je vous accorde qu'il existe des façons similaires de l'exprimer qui sont presque aussi expressives que sa syntaxe avec moins d'inconvénients. Mais sa syntaxe et le fait qu'il ait travaillé si dur pour l'obtenir montrent clairement la nécessité d'une amélioration du langage. Les performances passées indiquent que vous allez créer quelque chose de génial pour cela.
Charlie Flowers

Réponses:


147

Cela a une mauvaise interop. Par exemple, considérons cet exemple C # - F #

C #:

public class Class1
{
    public static void Foo(Func<object, string> f)
    {
        Console.WriteLine(f.Method.GetParameters()[0].Name);
    }
}

F#:

Class1.Foo(fun yadda -> "hello")

Résultat:

"arg" est imprimé (pas "yadda").

Par conséquent, les concepteurs de bibliothèques doivent soit éviter ces types d'abus, soit au moins fournir une surcharge `` standard '' (par exemple, qui prend le nom de chaîne comme paramètre supplémentaire) s'ils souhaitent avoir une bonne interopérabilité entre les langues .Net.


11
Non. Cette stratégie est tout simplement non portable. (Dans le cas où cela aiderait, à titre d'exemple dans l'autre sens, F # pourrait être capable de surcharger des méthodes qui ne diffèrent que par le type de retour (l'inférence de type peut le faire). Cela peut être exprimé dans le CLR. Mais F # le interdit, principalement parce que si vous avez fait cela, ces API ne seraient pas appelables à partir de C #.) En ce qui concerne l'interopérabilité, il existe toujours des compromis aux fonctionnalités `` de pointe '' concernant les avantages que vous obtenez par rapport à l'interopérabilité que vous échangez.
Brian

32
Je n'aime pas la non interopérabilité comme raison de ne pas faire quelque chose. Si l'interopérabilité est une exigence, faites-le, sinon, alors pourquoi s'en inquiéter? C'est YAGNI IMHO.
John Farrell

15
@jfar: Dans .NET CLR, l'interopérabilité terrestre a une toute nouvelle dimension, car les assemblys générés dans n'importe quel compilateur sont censés être consommés à partir de tout autre langage.
Remus Rusanu

25
Je suis d'accord que vous n'avez pas besoin d'être conforme à CLS, mais cela semble être une bonne idée si vous écrivez une bibliothèque ou un contrôle (et l'extrait de code qui démarre c'est à partir d'une grille, oui?) Sinon, vous êtes juste en train de limiter votre audience / clientèle
JMarsch

4
Peut-être que cela vaut la peine de changer: Func <objet, chaîne> en Expression << Func <objet, chaîne >> Et si vous contraignez le côté droit de l'expression à être simplement des constantes, vous pouvez avoir une implémentation qui fait ceci: public static IDictionary <chaîne, chaîne> Hachage (paramètres Expression <objet Func <, chaîne >> [] hachage) {Dictionnaire <chaîne, chaîne> valeurs = nouveau Dictionnaire <chaîne, chaîne> (); foreach (var func in hash) {values ​​[func.Parameters [0] .Name] = (string) ((ConstantExpression) func.Body) .Value; } renvoie des valeurs; }
davidfowl

154

Je trouve cela étrange non pas tant à cause du nom , mais parce que le lambda n'est pas nécessaire ; il pourrait utiliser un type anonyme et être plus flexible:

.Attributes(new { style = "width:100%", @class="foo", blip=123 });

C'est un modèle utilisé dans une grande partie d'ASP.NET MVC (par exemple), et a d' autres utilisations (une mise en garde , notez également les pensées d'Ayende si le nom est une valeur magique plutôt que spécifique à l'appelant)


4
Cela a également des problèmes d'interopérabilité; toutes les langues ne prennent pas en charge la création d'un type anonyme comme celui-ci à la volée.
Brian

5
J'adore la façon dont personne n'a vraiment répondu à la question, au lieu de cela, les gens proposent un argument "c'est mieux". : p Est-ce un abus ou non?
Sam Saffron

7
Je serais intéressé de voir la réaction d'Eric Lippert à cela. Parce que c'est en code FRAMEWORK . Et c'est tout aussi horrible.
Matt Hinze

26
Je ne pense pas que le problème soit la lisibilité après l'écriture du code. Je pense que le vrai problème est la capacité d'apprentissage du code. Qu'allez-vous penser quand votre intellisense dit .Attributes (object obj) ? Vous devrez aller lire la documentation (ce que personne ne veut faire) car vous ne saurez pas quoi passer à la méthode. Je ne pense pas que ce soit vraiment mieux que l'exemple de la question.
NotDan

2
@Arnis - pourquoi plus flexible: il ne repose pas sur le nom de paramètre implicite, ce qui pourrait (ne me citez pas) causer des problèmes avec certaines implémentations lambda (autres langages) - mais vous pouvez également utiliser des objets normaux avec des propriétés définies. Par exemple, vous pourriez avoir une HtmlAttributesclasse avec les attributs attendus (pour intellisense), et ignorer ceux qui ont des nullvaleurs ...
Marc Gravell

137

Je voulais juste jeter à mon avis (je suis l'auteur du composant de grille MvcContrib).

Il s'agit certainement d'un abus de langage - sans aucun doute. Cependant, je ne le considérerais pas vraiment comme contre-intuitif - lorsque vous regardez un appel à, Attributes(style => "width:100%", @class => "foo")
je pense que ce qui se passe est assez évident (ce n'est certainement pas pire que l'approche de type anonyme). D'un point de vue intellisense, je suis d'accord que c'est assez opaque.

Pour ceux qui sont intéressés, quelques informations générales sur son utilisation dans MvcContrib ...

J'ai ajouté cela à la grille comme préférence personnelle - je n'aime pas l'utilisation de types anonymes comme dictionnaires (avoir un paramètre qui prend "object" est tout aussi opaque que celui qui prend params Func []) et l'initialiseur de la collection Dictionary est plutôt verbeux (je ne suis pas non plus un fan des interfaces fluides, par exemple avoir à enchaîner plusieurs appels à un attribut ("style", "affichage: aucun"). Attribut ("classe", "foo") etc)

Si C # avait une syntaxe moins verbeuse pour les littéraux de dictionnaire, je n'aurais pas pris la peine d'inclure cette syntaxe dans le composant de grille :)

Je tiens également à souligner que l'utilisation de ceci dans MvcContrib est complètement facultative - ce sont des méthodes d'extension qui enveloppent les surcharges qui prennent un IDictionary à la place. Je pense qu'il est important que si vous fournissez une méthode comme celle-ci, vous souteniez également une approche plus «normale», par exemple pour l'interopérabilité avec d'autres langues.

De plus, quelqu'un a mentionné la `` surcharge de réflexion '' et je voulais juste souligner qu'il n'y a vraiment pas beaucoup de surcharge avec cette approche - il n'y a pas de réflexion d'exécution ou de compilation d'expression impliquée (voir http://blog.bittercoder.com /PermaLink,guid,206e64d1-29ae-4362-874b-83f5b103727f.aspx ).


1
J'ai également essayé de traiter certains des problèmes soulevés ici de manière plus approfondie sur mon blog: jeremyskinner.co.uk/2009/12/02/lambda-abuse-the-mvccontrib-hash
Jeremy Skinner

4
Il n'est pas moins opaque dans Intellisense que les objets anonymes.
Brad Wilson

22
+1 pour mentionner que l'interface est ajoutée via des méthodes d'extension facultatives . Les utilisateurs non C # (et toute personne offensée par l'abus de langage) peuvent simplement s'abstenir de l'utiliser.
Jørn Schou-Rode

50

je préférerais

Attributes.Add(string name, string value);

C'est beaucoup plus explicite et standard et rien n'est gagné en utilisant des lambdas.


20
Est-ce bien? html.Attributes.Add("style", "width:100%");ne lit pas aussi bien que style = "width:100%"(le HTML réel généré), alors qu'il style => "width:100%"est très proche de ce à quoi il ressemble dans le HTML résultant.
Jamie Penney

6
Leur syntaxe permet des astuces comme .Attributes (id => 'foo', @class => 'bar', style => 'width: 100%'). La signature de fonction utilise la syntaxe params pour un nombre variable d'arguments: Attributs (params Func <objet, objet> [] args). C'est très puissant, mais il m'a fallu un certain temps pour comprendre ce qu'il fait.
Remus Rusanu

27
@Jamie: Essayer de faire ressembler le code C # au code HTML serait une mauvaise raison pour les décisions de conception. Ce sont des langues complètement différentes à des fins complètement différentes, et elles ne devraient pas se ressembler.
Guffa

17
Un objet anonyme aurait tout aussi bien pu être utilisé, sans sacrifier la "beauté"? .Attributs (nouveau {id = "foo", @class = "bar", style = "width: 100%"}) ??
Funka

10
@Guffa Pourquoi serait-ce une mauvaise raison pour les décisions de conception? Pourquoi ne devraient-ils pas se ressembler? Par ce raisonnement, devraient-ils intentionnellement être différents? Je ne dis pas que vous vous trompez, je dis simplement que vous voudrez peut-être approfondir votre point de vue.
Samantha Branham

45

Bienvenue chez Rails Land :)

Il n'y a vraiment rien de mal à cela tant que vous savez ce qui se passe. (C'est lorsque ce genre de chose n'est pas bien documenté qu'il y a un problème).

L'intégralité du framework Rails repose sur l'idée d'une convention sur la configuration. Nommer les choses d'une certaine manière vous fait entrer dans une convention qu'ils utilisent et vous obtenez gratuitement de nombreuses fonctionnalités. Le respect de la convention de dénomination vous permet d'atteindre votre destination plus rapidement. Le tout fonctionne à merveille.

Un autre endroit où j'ai vu une astuce comme celle-ci est dans les assertions d'appels de méthode dans Moq. Vous passez un lambda, mais le lambda n'est jamais exécuté. Ils utilisent simplement l'expression pour s'assurer que l'appel de méthode a eu lieu et lèvent une exception sinon.


3
J'étais un peu hésitant, mais je suis d'accord. Mis à part la surcharge de réflexion, il n'y a pas de différence significative entre l'utilisation d'une chaîne comme dans Add () et l'utilisation d'un nom de paramètre lambda. Au moins, je peux penser. Vous pouvez le nettoyer et taper "sytle" sans remarquer dans les deux sens.
Samantha Branham

5
Je ne pouvais pas comprendre pourquoi ce n'était pas bizarre pour moi, puis je me suis souvenu de Rails. : D
Allyn

43

C'est horrible à plus d'un niveau. Et non, cela n'a rien à voir avec Ruby. C'est un abus de C # et .NET.

Il y a eu de nombreuses suggestions sur la façon de le faire de manière plus simple: tuples, types anonymes, une interface fluide et ainsi de suite.

Ce qui le rend si mauvais, c'est que c'est juste un moyen de s'imaginer pour son propre bien:

  • Que se passe-t-il lorsque vous devez appeler cela à partir de Visual Basic?

    .Attributes(Function(style) "width:100%")

  • C'est complètement contre-intuitif, et intellisense fournira peu d'aide pour comprendre comment transmettre des choses.

  • C'est inutilement inefficace.

  • Personne ne saura comment le maintenir.

  • Quel est le type d'argument entrant dans les attributs? est-ce Func<object,string>? Comment cette intention est-elle révélatrice? Que va dire votre documentation intellisense, "Veuillez ignorer toutes les valeurs de l'objet"?

Je pense que vous avez tout à fait raison d'avoir ces sentiments de répulsion.


4
Je dirais - c'est complètement intuitif. :)
Arnis Lapsa

4
Vous dites que cela n'a rien à voir avec Ruby. Mais c'est une horrible ressemblance avec la syntaxe de Ruby pour spécifier les clés et les valeurs d'une table de hachage.
Charlie Flowers

3
Code qui rompt sous la conversion alpha! Ouais!
Phil

3
@Charlie, syntaxiquement, cela ressemble, sémantiquement, c'est très différent.
Sam Saffron

39

Je suis dans le camp de la "brillance syntaxique", s'ils le documentent clairement et que ça a l'air vraiment cool, il n'y a presque aucun problème avec ça imo!


10
Amen, frère. Amen (2e amen requis pour répondre à la longueur minimale pour les commentaires :)
Charlie Flowers

Votre commentaire seul était bien plus que nécessaire. Mais alors, vous ne pouvez pas simplement Amen une fois, puis mettre votre commentaire: D
Sleeper Smith

37

Les deux. C'est un abus des expressions lambda ET de la brillance de la syntaxe.


16
C'est donc un brillant abus syntaxique des expressions lambda? Je pense que je suis d'accord :)
Seth Petry-Johnson

21

Je n'ai presque jamais rencontré ce genre d'utilisation. Je pense que c'est "inapproprié" :)

Ce n'est pas un mode d'utilisation courant, il est incompatible avec les conventions générales. Ce type de syntaxe a bien sûr des avantages et des inconvénients:

Les inconvénients

  • Le code n'est pas intuitif (les conventions habituelles sont différentes)
  • Il a tendance à être fragile (le renommage du paramètre cassera la fonctionnalité).
  • C'est un peu plus difficile à tester (truquer l'API nécessitera l'utilisation de la réflexion dans les tests).
  • Si l'expression est utilisée intensivement, elle sera plus lente en raison de la nécessité d'analyser le paramètre et pas seulement la valeur (coût de réflexion)

Avantages

  • C'est plus lisible après que le développeur s'est ajusté à cette syntaxe.

Conclusion - dans la conception de l'API publique, j'aurais choisi une méthode plus explicite.


2
@Elisha - vos avantages et inconvénients sont inversés. Au moins j'espère que vous ne dites pas qu'un Pro a un code "pas intuitif". ;-)
Metro Smurf

Dans ce cas particulier, le nom du paramètre lambda et le paramètre de chaîne sont tous deux fragiles. C'est comme utiliser Dynamic pour l'analyse XML - c'est approprié parce que vous ne pouvez pas être sûr de XML de toute façon.
Arnis Lapsa

19

Non, ce n'est certainement pas une pratique courante. C'est contre-intuitif, il n'y a aucun moyen de simplement regarder le code pour comprendre ce qu'il fait. Vous devez savoir comment il est utilisé pour comprendre comment il est utilisé.

Au lieu de fournir des attributs à l'aide d'un tableau de délégués, les méthodes de chaînage seraient plus claires et fonctionneraient mieux:

.Attribute("style", "width:100%;").Attribute("class", "test")

Bien que ce soit un peu plus à taper, c'est clair et intuitif.


6
Vraiment? Je savais exactement ce que cet extrait de code voulait dire quand je l'ai regardé. Ce n'est pas si obtus que si vous êtes très strict. On pourrait donner le même argument à propos de la surcharge + pour la concaténation de chaînes, et que nous devrions toujours utiliser une méthode Concat () à la place.
Samantha Branham

4
@Stuart: Non, vous ne saviez pas exactement, vous deviniez simplement en fonction des valeurs utilisées. N'importe qui peut faire cette supposition, mais deviner n'est pas un bon moyen de comprendre le code.
Guffa

11
Je suppose que l'utilisation .Attribute("style", "width:100%")me donne style="width:100%", mais pour autant que je sache, cela pourrait me donner foooooo. Je ne vois pas la différence.
Samantha Branham

5
"Deviner en fonction des valeurs utilisées" est TOUJOURS ce que vous faites lorsque vous regardez du code. Si vous rencontrez un appel à stream.close (), vous supposez qu'il ferme un flux, mais il pourrait tout aussi bien faire quelque chose de complètement différent.
Wouter Lievens,

1
@Wouter: Si vous devinez TOUJOURS lorsque vous lisez du code, vous devez avoir de grandes difficultés à lire le code ... Si je vois un appel à une méthode nommée "close", je peux comprendre que l'auteur de la classe ne connaît pas les conventions de dénomination , donc j'hésiterais beaucoup à tenir tout pour acquis sur ce que fait la méthode.
Guffa

17

Puis-je l'utiliser pour inventer une phrase?

lambda magique (n): une fonction lambda utilisée uniquement dans le but de remplacer une chaîne magique.


ouais ... c'est marrant. et peut-être que c'est un peu magique, dans le sens de l'absence de sécurité au moment de la compilation, y a-t-il un endroit où cette utilisation entraînerait l'exécution au lieu d'erreurs au moment de la compilation?
Maslow

17

Quel est le problème avec les éléments suivants:

html.Attributes["style"] = "width:100%";

16

Toute cette diatribe sur "horreur" est un groupe de gars c # de longue date exagérant (et je suis un programmeur C # de longue date et toujours un très grand fan du langage). Il n'y a rien d'horrible dans cette syntaxe. C'est simplement une tentative de faire ressembler la syntaxe à ce que vous essayez d'exprimer. Moins il y a de «bruit» dans la syntaxe de quelque chose, plus le programmeur peut le comprendre facilement. Réduire le bruit dans une seule ligne de code n'aide que peu, mais laissez cela s'accumuler dans de plus en plus de code, et cela s'avère être un avantage substantiel.

Il s'agit d'une tentative de l'auteur de viser les mêmes avantages que les DSL vous offrent - lorsque le code "ressemble" à ce que vous essayez de dire, vous avez atteint un endroit magique. Vous pouvez débattre de savoir si cela est bon pour l'interopérabilité, ou si c'est assez plus agréable que les méthodes anonymes pour justifier une partie du coût de la «complexité». Assez juste ... donc dans votre projet, vous devez faire le bon choix d'utiliser ou non ce type de syntaxe. Mais quand même ... c'est une tentative intelligente d'un programmeur pour faire ce que, en fin de compte, nous essayons tous de faire (que nous le réalisions ou non). Et ce que nous essayons tous de faire, c'est ceci: "Dites à l'ordinateur ce que nous voulons qu'il fasse dans un langage aussi proche que possible de la façon dont nous pensons à ce que nous voulons qu'il fasse."

Se rapprocher de l'expression de nos instructions aux ordinateurs de la même manière que nous pensons en interne est une clé pour rendre les logiciels plus faciles à maintenir et plus précis.

EDIT: J'avais dit "la clé pour rendre les logiciels plus faciles à maintenir et plus précis", ce qui est un peu exagérément naïf de licorne. Je l'ai changé en "une clé".


12

C'est l'un des avantages des arborescences d'expression - on peut examiner le code lui-même pour des informations supplémentaires. C'est ainsi que l' .Where(e => e.Name == "Jamie")on peut convertir la clause SQL Where équivalente. C'est une utilisation intelligente des arbres d'expression, mais j'espère que cela ne va pas plus loin. Tout ce qui est plus complexe sera probablement plus difficile que le code qu'il espère remplacer, donc je soupçonne qu'il se limitera automatiquement.


Est un point valable, mais la vérité dans la publicité: LINQ est livré avec tout un ensemble d'attributs comme TableAttribute et ColumnAttribute qui en font une affaire plus légitime. Le mappage linq examine également les noms de classe et les noms de propriété, qui sont sans doute plus stables qu'un nom de paramètre.
Remus Rusanu

Je suis en accord avec vous. J'ai légèrement changé d'avis à ce sujet après avoir lu ce qu'Eric Lippert / Anders Helsberg / etc avait à dire à ce sujet. Je pensais que je laisserais cette réponse car elle est toujours un peu utile. Pour ce que ça vaut, je pense maintenant que ce style de travail avec HTML est bien, mais il ne correspond pas au langage.
Jamie Penney

7

C'est une approche intéressante. Si vous avez contraint le côté droit de l'expression à être des constantes uniquement, vous pouvez implémenter à l'aide de

Expression<Func<object, string>>

Ce que je pense est ce que vous voulez vraiment au lieu du délégué (vous utilisez le lambda pour obtenir les noms des deux côtés) Voir la mise en œuvre naïve ci-dessous:

public static IDictionary<string, string> Hash(params Expression<Func<object, string>>[] hash) {
    Dictionary<string, string> values = new Dictionary<string,string>();
    foreach (var func in hash) {
        values[func.Parameters[0].Name] = ((ConstantExpression)func.Body).Value.ToString();
    }
    return values;
}

Cela pourrait même répondre au problème d'interopérabilité entre les langues qui a été mentionné plus tôt dans le fil.


6

Le code est très intelligent, mais il provoque potentiellement plus de problèmes qu'il résout.

Comme vous l'avez souligné, il existe maintenant une dépendance obscure entre le nom du paramètre (style) et un attribut HTML. Aucune vérification du temps de compilation n'est effectuée. Si le nom du paramètre est mal tapé, la page n'aura probablement pas de message d'erreur d'exécution, mais un bug logique beaucoup plus difficile à trouver (pas d'erreur, mais un comportement incorrect).

Une meilleure solution serait d'avoir un membre de données qui peut être vérifié au moment de la compilation. Donc au lieu de ça:

.Attributes(style => "width:100%");

le code avec une propriété Style peut être vérifié par le compilateur:

.Attributes.Style = "width:100%";

ou même:

.Attributes.Style.Width.Percent = 100;

C'est plus de travail pour les auteurs du code, mais cette approche tire parti de la forte capacité de vérification de type de C #, qui aide à empêcher les bogues d'entrer dans le code en premier lieu.


3
J'apprécie la vérification à la compilation, mais je pense que cela se résume à une question d'opinion. Peut-être que quelque chose comme de nouveaux Attributes () {Style: "width: 100%"} gagnerait plus de gens à cela, car c'est plus concis. Pourtant, l'implémentation de tout ce que HTML permet est un travail énorme et je ne peux pas blâmer quelqu'un pour simplement utiliser des chaînes / lambdas / des classes anonymes.
Samantha Branham

5

en effet, cela ressemble à Ruby =), au moins pour moi, l'utilisation d'une ressource statique pour une "recherche" dynamique ultérieure ne convient pas aux considérations de conception d'api, espérons que cette astuce est facultative dans cette api.

Nous pourrions hériter d'IDictionary (ou non) et fournir un indexeur qui se comporte comme un tableau php lorsque vous n'avez pas besoin d'ajouter une clé pour définir une valeur. Ce sera une utilisation valide de la sémantique .net, pas seulement c #, et il faudra toujours de la documentation.

J'espère que cela t'aides


4

À mon avis, c'est un abus des lambdas.

En ce qui concerne l'éclat de la syntaxe, je trouve tout style=>"width:100%"simplement déroutant. Particulièrement à cause de la =>place de=


4

À mon humble avis, c'est une façon cool de le faire. Nous aimons tous le fait que nommer un contrôleur de classe en fera un contrôleur dans MVC, n'est-ce pas? Il y a donc des cas où la dénomination est importante.

L'intention est également très claire ici. Il est très facile de comprendre que .Attribute( book => "something")cela entraînera book="something"et .Attribute( log => "something")entraîneralog="something"

Je suppose que cela ne devrait pas être un problème si vous le traitez comme une convention. Je suis d'avis que tout ce qui vous fait écrire moins de code et rend l'intention évidente est une bonne chose.


4
Nommer un contrôleur de classe ne fera pas de squat si vous n'héritez pas trop du contrôleur ...
Jordan Wallwork

3

Si les noms de méthode (func) sont bien choisis, alors c'est une excellente façon d'éviter les maux de tête de maintenance (c'est-à-dire: ajouter un nouveau func, mais j'ai oublié de l'ajouter à la liste de mappage des paramètres de fonction). Bien sûr, vous devez le documenter fortement et vous feriez mieux de générer automatiquement la documentation des paramètres à partir de la documentation des fonctions de cette classe ...


1

Je pense que ce n'est pas mieux que des "cordes magiques". Je ne suis pas non plus très fan des types anonymes pour cela. Il a besoin d'une approche meilleure et fortement typée.

En utilisant notre site, vous reconnaissez avoir lu et compris notre politique liée aux cookies et notre politique de confidentialité.
Licensed under cc by-sa 3.0 with attribution required.