8
votes

Remplacement d'une méthode régulière avec une méthode anonyme en C # / Linq

J'ai une requête LINQ qui ressemble à ceci:

...
select
    () => { f.MissingProp = b.MissingProp; return f }


2 commentaires

Je ne connais pas la syntaxe Linq assez bien pour l'écrire, mais ne serait-il pas mieux la mutation d'une déclaration de forach (YourLinqQuery)? Avoir une mutation choisie, les objets semblent déroutants.


@Doc Brown, c'était en fait juste une faute de frappe dans mon exemple (mon vrai code dit est égal à ). Corrigé maintenant.


5 Réponses :


3
votes

Vous pouvez donner des types à vos paramètres dans une expression lambda, mais vous devez utiliser différents noms puisque vous utilisez déjà F et B dans la requête.

(FOO F1, BAR B1) => ... < / p>

edit xxx


5 commentaires

Cela ne fonctionne pas. Il ne sait pas qu'il devrait passer dans f et B . J'ai aussi la même erreur que si j'utilise () => {...} (voir ma mise à jour).


Deuxième fois le charme :) Eh bien, sauf le deuxième de devrait être un joindre . Mais, sinon, c'est ma solution préférée jusqu'à présent.


J'ai remarqué un autre problème mineur ... il devrait être {foobar.f.barid = foobar.b.id; retourner foobar.f}; . Sinon, vous pouvez définir explicitement définir les noms de propriété pour le type anonyme dans nouveau {f, b} comme ceci: nouveau {foo = f, bar = b} .


Ah, oui ... c'est bien bien sûr :-) Je ne m'embête habituellement pas avec les noms de propriété quand tout ce que je me soucie vraiment de la structure. Il est également un peu plus conforme à la programmation fonctionnelle où vous traitez habituellement avec un système de type structural plutôt qu'un système nominal. En plus, je pense que l'une des raisons pour lesquelles j'ai personnellement profiter de la programmation fonctionnelle, c'est que cela vous permet d'éviter l'un des deux problèmes les plus difficiles en informatique (invalidation du cache et des choses de dénomination :-)). Acclamations...


J'ai édité votre réponse pour supprimer les erreurs dont nous avons parlé parce que je veux la marquer comme la réponse.



1
votes

Sélectionner (F2, B2) => {F2.MissingProp = B2.MissingProp; Retour F2}


1 commentaires

Cela ne fonctionne pas. Il ne sait pas qu'il devrait passer dans f et B . J'ai aussi la même erreur que si j'utilise () => {...} (voir ma mise à jour).



1
votes

Réécrivez ceci avec la syntaxe Lambda.

var vf2 = foos.Join(bars, f => f.id, b => b.id, (foo, bar) => { foo.MissingProp = bar.MissingProp; return foo; });


6 commentaires

Pour une raison quelconque, cela provoque une erreur avec la clause de jointure (même si je n'ai pas changé la clause de jointure): Le type d'une des expressions de la clause de jointure est incorrect. Type Inference a échoué dans l'appel à «rejoindre».


C'est parce que lorsque vous sélectionnez que vous le disiez quel type de retour, SELECT () suppose que vous retournez un type de délégué. Je pense que vous devriez rester avec votre méthode.


Hmm ... peut-être que cela ne peut pas être fait. Mais pourquoi ne peut-il pas déduire le type de retour de retour f; ? Il sait F est un foo .


@Dan, c'est que parce que SELECT () implique de sélectionner un nouveau délégué, ne pas sélectionner Nouveau FOO.


Wow, cela fonctionne avec des méthodes de vulgarisation. Je déteste vraiment la lisibilité de la méthode d'extension joindre () , mais ça marche. Merci de votre aide.


@Dan, oui la lisibilité n'est pas géniale .. mais cela fait ce que vous le demandez. Si vous souhaitez une lisibilité, vous devriez rester avec la méthode ou utiliser une boucle de régie comme suggérée. Bonne chance :)



5
votes

Je pense icambron em> a raison, IMHO La version la mieux lisible est la suivante:

  var fooBar = from 
                 f in foos
               join 
                 b in bars
                 on f.BarId equals b.Id 
               select new {f,b};

   foreach(var x in fooBar)
        x.f.MissingProp = x.b.MissingProp;

   // EDIT due to comments: add this if you 
   // need IEnumerable<Foo> returned
   return fooBar.Select(fb => fb.f);


5 commentaires

Merci +1. J'avais pensé à utiliser foreach mais je suppose que j'essayais d'être trop chic :) C'est une bonne solution.


Oups, un problème. Cela me laisse avec un ienumerable mais j'ai besoin d'un ienumerable . Je pense que si vous ajoutez retour foobar.select (fb => fb.f); à votre réponse, ce sera correct.


Vous devriez également être capable de faire var foobar = (....). Foreach (....); et une ligne it!


@Danthman: édité, mais vous devriez changer le type de retour de AddMissingProp pour rendre la question originale adaptée à la réponse modifiée :-)


@Chris: foreach fonctionne sur le tableau <>, pas sur iEnumerable <>. Et je ne pense pas que cela rendra mieux lisible.



1
votes

Si le compilateur ne peut pas déduire le type correct à passer à une Lambda, vous pouvez bien sûr spécifier le type vous-même.

Cela devrait fonctionner correctement: P>

select
    (Foo f2, b) => { f2.MissingProp = b.MissingProp; return f2; }


4 commentaires

En ce qui concerne le code incomplet, j'ai oublié ma déclaration de retour. Juste la corrigé.


Vous avez également manqué le point-virgule d'extrémité après la requête LINQ. Vous devriez toujours s'efforcer de copier et de coller ce que vous avez dans votre code et n'essayez pas de le simplifier. Vous seriez émerveillé de ce que les gens ici sont capables de lire du code :)


Pas capable de faire fonctionner votre solution. Même si j'utilise (foo f2, bar B) au lieu de (foo f2, b) , je suis toujours signalé pour ma clause de jointure.


Je suis d'accord sur la copie / la pâte ... Dans ce cas, il y avait toutefois des informations exclusives dans mon code.