54 votes

Quand ne pas utiliser les expressions lambda

Beaucoup de questions sont répondues sur un Débordement de Pile avec les membres de la spécification de la façon de résoudre ces monde réel/temps des problèmes à l'aide des expressions lambda.

Sommes-nous trop de celui-ci, et nous étudions l'impact sur les performances de l'utilisation des expressions lambda?

J'ai trouvé quelques articles qui explore l'impact sur les performances de lambda vs anonyme délégués vs for/foreach boucles avec des résultats différents

  1. Anonyme Délégués vs les Expressions Lambda vs les Appels de la Fonction de Performance
  2. La Performance de foreach vs Liste.ForEach
  3. .NET/C# Performance de la Boucle de Test (POUR, FOREACH, LINQ, & Lambda).
  4. DataTable.Sélectionnez est plus rapide que LINQ

Quels devraient être les critères d'évaluation au moment de choisir la solution appropriée? Sauf pour la raison évidente qu'il est plus code concis et lisibles lors de l'utilisation lambda.

35voto

Rui Craveiro Points 1649

Même si je vais me concentrer sur un point, j'ai commencer par vous donner de mes 2 cents sur l'ensemble de la question de la performance. À moins que les différences sont grandes ou de l'utilisation est intensive, je n'ai pas pris la peine de microsecondes qui ne sont pas d'une quelconque différence visible à l'utilisateur. Je tiens à souligner que je ne n'avez pas de soins lors de l'examen de la non-intensif appelées méthodes. Où je dois performance spéciale de considérations sur la conception de l'application elle-même. - Je me soucier de la mise en cache, à propos de l'utilisation des threads, sur des moyens astucieux pour l'appel de méthodes (si plusieurs appels ou essayer de faire un seul appel), que ce soit à la piscine des connexions ou non, etc., etc. En fait j'ai l'habitude de ne pas se focaliser sur la performance brute, mais sur scalibility. Je ne m'inquiète pas si il fonctionne mieux par une minuscule tranche de nanoseconde pour un seul utilisateur, mais je me soucie beaucoup avoir la possibilité de charger le système avec de grandes quantités d'utilisateurs simultanés, sans remarquer l'impact.

Cela dit, voici mon avis sur le point 1. J'aime les méthodes anonymes. Ils me donnent une grande flexibilité et le code de l'élégance. L'autre grande caractéristique sur les méthodes anonymes est qu'ils me permettent d'utiliser directement les variables locales de la méthode conteneur (à partir d'un C# point de vue, non pas à partir d'un IL point de vue, bien sûr). Ils m'épargner des charges de code souvent. Quand dois-je utiliser des méthodes anonymes? Evey seule fois sur le morceau de code que j'ai besoin n'est pas nécessaire d'ailleurs. Si elle est utilisée dans deux endroits différents, je n'aime pas copier-coller comme un réutiliser la technique, donc je vais utiliser une plaine ol délégué. Donc, tout comme shoosh répondu, il n'est pas bon d'avoir la duplication de code. En théorie, il n'existe pas de différences de performances comme anonyms sont C# astuces, pas de IL des trucs.

La plupart de ce que je pense sur les méthodes anonymes s'applique aux expressions lambda, que ce dernier peut être utilisé comme une syntaxe compacte pour représenter les méthodes anonymes. Supposons la méthode suivante:

    public static void DoSomethingMethod(string[] names, Func<string, bool> myExpression)
    {
        Console.WriteLine("Lambda used to represent an anonymous method");
        foreach (var item in names)
        {
            if (myExpression(item))
                Console.WriteLine("Found {0}", item);
        }
    }

Il reçoit un tableau de chaînes de caractères et pour chacun d'eux, il va appeler la méthode adoptée. Si cette méthode retourne true, on va dire "Trouvé...". Vous pouvez appeler cette méthode de la façon suivante:

        string[] names = {"Alice", "Bob", "Charles"};
        DoSomethingMethod(names, delegate(string p) { return p == "Alice"; });

Mais, vous pouvez aussi appeler cela de la manière suivante:

        DoSomethingMethod(names, p => p == "Alice");

Il n'y a pas de différence dans IL entre les deux, l'une à l'aide de l'expression Lambda est beaucoup plus lisible. Encore une fois, il n'y a pas d'impact sur les performances de tous ces compilateur C# astuces (pas de compilateur JIT de trucs). Tout comme je n'ai pas l'impression de nous abuser des méthodes anonymes, je n'ai pas l'impression de nous abuser des Lambda expressions pour représenter les méthodes anonymes. Bien sûr, la même logique s'applique à code à répétition: à ne pas faire lambdas, l'utilisation régulière des délégués. Il existe d'autres restrictions qui vous conduira à revenir à des méthodes anonymes ou de la plaine des délégués, comme ou ref argument de passage.

Les autres belles choses sur les expressions Lambda, c'est que l'exacte même syntaxe n'a pas besoin de représenter une méthode anonyme. Les expressions Lambda peut aussi représenter... vous l'aurez deviné, les expressions. Prenons l'exemple suivant:

    public static void DoSomethingExpression(string[] names, System.Linq.Expressions.Expression<Func<string, bool>> myExpression)
    {
        Console.WriteLine("Lambda used to represent an expression");
        BinaryExpression bExpr = myExpression.Body as BinaryExpression;
        if (bExpr == null)
            return;
        Console.WriteLine("It is a binary expression");
        Console.WriteLine("The node type is {0}", bExpr.NodeType.ToString());
        Console.WriteLine("The left side is {0}", bExpr.Left.NodeType.ToString());
        Console.WriteLine("The right side is {0}", bExpr.Right.NodeType.ToString());
        if (bExpr.Right.NodeType == ExpressionType.Constant)
        {
            ConstantExpression right = (ConstantExpression)bExpr.Right;
            Console.WriteLine("The value of the right side is {0}", right.Value.ToString());
        }
     }

Avis légèrement différent de la signature. Le deuxième paramètre reçoit une expression et non d'un délégué. Le moyen d'appeler cette méthode serait:

    DoSomethingExpression(names, p => p == "Alice");

Ce qui est exactement le même que l'appel que nous avons fait lors de la création d'une méthode anonyme avec un lambda. La différence ici est que nous ne sommes pas de la création d'une méthode anonyme, mais la création d'une arborescence d'expression. C'est en raison de ces arbres d'expression que l'on peut alors traduire les expressions lambda de SQL, qui est ce que Linq 2 SQL, par exemple, au lieu d'exécuter des trucs dans le moteur pour chaque clause comme le Où, le Sélectionner, etc. La bonne chose est que la syntaxe d'appel est la même que vous êtes en train de créer une méthode anonyme ou l'envoi d'une expression.

26voto

Jerry Nixon - MSFT Points 12256

Ma réponse ne sera pas populaire.

Je crois Lambda sont à 99% toujours le meilleur choix pour trois raisons.

Tout d'abord, il n'y a ABSOLUMENT rien de mal à assumer vos développeurs sont intelligents. D'autres réponses ont un principe sous-jacent que chaque développeur mais vous est stupide. De ne pas faire.

Deuxièmement, Lamdas (et al) sont une syntaxe moderne - et demain, ils seront de plus en plus courants qu'ils ne le sont aujourd'hui. Votre projet de code devrait s'écouler à partir actuels et émergents des conventions.

Troisièmement, l'écriture de code "à l'ancienne" peut sembler plus facile pour vous, mais ce n'est pas plus facile pour le compilateur. C'est important, les approches traditionnelles ont peu de chance d'être améliorée, car le compilateur rev ed. Les Lambdas (et al) qui repose sur le compilateur pour élargir peuvent bénéficier en tant que le compilateur traite mieux avec le temps.

Pour résumer:

  1. Les développeurs peuvent le manipuler
  2. Tout le monde le fait
  3. Il y a du potentiel pour l'avenir

Encore une fois, je sais que ce ne sera pas une réponse. Et croyez-moi", Simple est le Meilleur" c'est mon mantra. L'entretien est un aspect important de n'importe quelle source. - Je l'obtenir. Mais je pense que nous sommes d'éclipser la réalité avec certains clichés règles du pouce.

// Jerry

19voto

shoosh Points 34322

Duplication de code.
Si vous vous retrouvez à écrire la même fonction anonyme plusieurs fois, cela ne devrait pas en être une.

14voto

Marc Gravell Points 482669

Eh bien, quand nous parlons de combat délégué d'utilisation, il ne devrait pas y avoir de différence entre lambda et les méthodes anonymes, ils sont le même, mais avec une syntaxe différente. Et nommé méthodes (utilisé en tant que délégués) sont également identiques à partir de l'exécution de point de vue. La différence, alors, entre l'utilisation de délégués, vs de code en ligne - c'est à dire

list.ForEach(s=>s.Foo());
// vs.
foreach(var s in list) { s.Foo(); }

(où je m'attends à ce que celle-ci soit plus rapide)

Et de même, si l'on parle de rien d'autres que des objets en mémoire, les lambdas sont l'un de vos outils les plus puissants en termes de maintien de la vérification de type (plutôt que de l'analyse de chaînes de tous les temps).

Certes, il existe des cas où un simple foreach avec le code sera plus rapide que l'LINQ version, car il y aura moins invoque à faire, et invoque un coût faible mais mesurable temps. Cependant, dans de nombreux cas, le code est tout simplement pas le goulot d'étranglement, et le plus simple de code (en particulier pour les groupes, etc) vaut beaucoup plus que quelques nanosecondes.

Notez également que dans .NET 4.0 supplémentaire Expression des nœuds pour des choses comme des boucles, des virgules, etc. La langue ne les supporte pas, mais le moteur d'exécution ne. Je mentionne ce que pour compléter: je ne suis certainement pas dire que vous devriez utiliser manuel Expression constructions foreach !

6voto

Razzie Points 14705

Je dirais que les différences de rendement sont généralement de petite taille (et dans le cas de boucles, de toute évidence, si vous regardez les résultats de la 2ème article (btw, Jon Skeet a un article similaire ici)) que vous devriez jamais choisir une solution pour des raisons de performances, sauf si vous êtes l'écriture d'un morceau de logiciel où la performance est absolument la non-exigence fonctionnelle et vous avez vraiment à faire des micro-optimalizations.

Quand choisir quoi? Je suppose que cela dépend de la situation, mais aussi la personne. Juste comme exemple, certaines personnes perfer Liste.Foreach dans un normal la boucle foreach. J'ai personnellement préfère le dernier, comme il est habituellement plus lisible, mais qui suis-je pour argumenter contre cela?

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X