202 votes

Fonction locale vs Lambda C # 7.0

Je suis en train de regarder les nouvelles implémentations en C# 7.0 et je trouve intéressant qu'ils ont mis en œuvre des fonctions locales, mais je ne peux pas imaginer un scénario où une fonction locale serait préférée à une expression lambda, et quelle est la différence entre les deux.

Je comprends que les lambdas sont anonymous fonctions en attendant les fonctions locales ne sont pas, mais je ne peux pas comprendre un scénario réel, où la fonction locale a des avantages sur les expressions lambda

Un exemple serait très apprécié. Merci.

299voto

svick Points 81772

Ceci s'explique par Mads Torgersen en C# Design Notes de Réunion où les fonctions ont d'abord été discuté:

Vous voulez une fonction d'assistance. Vous utilisez uniquement de l'intérieur d'une seule fonction, et il est probable utilise des variables et des paramètres de type qui sont dans la portée de cette fonction contenante. D'autre part, contrairement à un lambda vous n'en avez pas besoin, comme une première classe de l'objet, de sorte que vous n'avez pas soin de lui donner un type délégué et d'allouer un délégué de l'objet. Aussi, vous voudrez peut-être lui être récursive ou générique, ou de l'appliquer comme un itérateur.

Pour développer un peu plus, les avantages sont les suivants:

  1. Les performances.

    Lors de la création d'un lambda, un délégué doit être créé, ce qui est inutile, de l'allocation dans ce cas. Les fonctions locales sont vraiment juste des fonctions, pas de délégués sont nécessaires.

    Aussi, les fonctions locales sont plus efficaces pour la capture de variables locales: les lambdas généralement la capture de variables dans une classe, tandis que les fonctions peuvent utiliser un struct (passé à l'aide de ref), ce qui évite une allocation.

    Cela signifie également d'appeler des fonctions locales est moins cher et ils peuvent être inline, ce qui pourrait accroître encore plus les performances.

  2. Les fonctions locales peuvent être récursives.

    Les Lambdas peuvent être récursifs trop, mais il nécessite maladroit code, si vous commencez par attribuer null d'un délégué de la variable, puis le lambda. Les fonctions locales peuvent naturellement être récursive (y compris mutuellement récursives).

  3. Les fonctions locales peuvent être génériques.

    Les Lambdas ne peut pas être générique, car ils doivent être assignée à une variable avec un type de béton (type pouvez utiliser générique variables à partir de l'extérieur de la portée, mais ce n'est pas la même chose).

  4. Les fonctions locales peuvent être mises en œuvre comme un itérateur.

    Les Lambdas ne peut pas utiliser l' yield return (et yield break) mot-clé pour mettre en oeuvre IEnumerable<T>-le retour de fonction. Les fonctions locales peut.

  5. Les fonctions locales regarder mieux.

    Ce n'est pas mentionné dans la citation ci-dessus et peut-être juste ma préférence personnelle, mais je pense que la normale de la syntaxe de la fonction, c'est mieux que l'affectation d'un lambda à un délégué de la variable. Les fonctions locales sont également plus succincte.

    Comparer:

    int add(int x, int y) => x + y;
    Func<int, int, int> add = (x, y) => x + y;
    

92voto

Tim Pohlmann Points 1714

En plus de la réponse géniale de svick, les fonctions locales présentent un avantage supplémentaire:
Ils peuvent être définis n'importe où dans la fonction, même après l'instruction return .

 public double DoMath(double a, double b)
{
    var resultA = f(a);
    var resultB = f(b);
    return resultA + resultB;

    double f(double x) => 5 * x + 3;
}
 

0voto

J'utilise les fonctions inline pour éviter la collecte des ordures pression spécialement lorsque vous traitez avec de plus en cours d'exécution des méthodes. Dire que l'on souhaite obtenir 2 ans, ou les données du marché pour un symbole. Aussi, on peut emballer beaucoup de fonctionnalités et une logique d'entreprise si l'on en a besoin.

ce que l'on ouvre une socket de connexion au serveur et en boucle sur les données de la liaison d'un événement pour un événement. On peut penser de la même manière qu'une classe est conçu, un seul n'est pas l'écriture de méthodes d'assistance partout qui sont vraiment seulement pour une pice de fonctionnalité. ci-dessous quelques exemples de la façon dont cela pourrait ressembler, veuillez noter que je suis à l'aide de variables et de l ' "aide" méthodes sont en dessous de la enfin. En la Finalement j'ai bien supprimer les gestionnaires d'événements, si je Change de classe serait externe/injectés je n'aurais aucune attente de gestionnaire d'événements registrated

void List<HistoricalData> RequestData(Ticker ticker, TimeSpan timeout)
{
    var socket= new Exchange(ticker);
    bool done=false;
    socket.OnData += _onData;
    socket.OnDone += _onDone;
    var request= NextRequestNr();
    var result = new List<HistoricalData>();
    var start= DateTime.Now;
    socket.RequestHistoricalData(requestId:request:days:1);
    try
    {
      while(!done)
      {   //stop when take to long….
        if((DateTime.Now-start)>timeout)
           break;
      }
      return result;

    }finally
    {
        socket.OnData-=_onData;
        socket.OnDone-= _onDone;
    }


   void _OnData(object sender, HistoricalData data)
   {
       _result.Add(data);
   }
   void _onDone(object sender, EndEventArgs args)
   {
      if(args.ReqId==request )
         done=true;
   } 
}

Vous pouvez voir les avantages, comme mentionné ci-dessous, vous pouvez voir ici un exemple de mise en œuvre. L'espoir qui aide à expliquer les avantages.

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