What is the difference between lambdas and delegates in the .NET Framework?

后端 未结 17 1332
小蘑菇
小蘑菇 2020-12-12 10:45

I get asked this question a lot and I thought I\'d solicit some input on how to best describe the difference.

相关标签:
17条回答
  • 2020-12-12 11:11

    A delegate is a reference to a method with a particular parameter list and return type. It may or may not include an object.

    A lambda-expression is a form of anonymous function.

    0 讨论(0)
  • 2020-12-12 11:13

    lambdas are simply syntactic sugar on a delegate. The compiler ends up converting lambdas into delegates.

    These are the same, I believe:

    Delegate delegate = x => "hi!";
    Delegate delegate = delegate(object x) { return "hi";};
    
    0 讨论(0)
  • 2020-12-12 11:15

    Lambdas are simplified versions of delegates. They have some of the the properties of a closure like anonymous delegates, but also allow you to use implied typing. A lambda like this:

    something.Sort((x, y) => return x.CompareTo(y));
    

    is a lot more concise than what you can do with a delegate:

    something.Sort(sortMethod);
    ...
    
    private int sortMethod(SomeType one, SomeType two)
    {
        one.CompareTo(two)
    }
    
    0 讨论(0)
  • 2020-12-12 11:15

    Heres an example I put up awhile on my lame blog. Say you wanted to update a label from a worker thread. I've got 4 examples of how to update that label from 1 to 50 using delegates, anon delegates and 2 types of lambdas.

     private void button2_Click(object sender, EventArgs e) 
         { 
             BackgroundWorker worker = new BackgroundWorker(); 
             worker.DoWork += new DoWorkEventHandler(worker_DoWork); 
             worker.RunWorkerAsync(); 
         } 
    
         private delegate void UpdateProgDelegate(int count); 
         private void UpdateText(int count) 
         { 
             if (this.lblTest.InvokeRequired) 
             { 
                 UpdateProgDelegate updateCallBack = new UpdateProgDelegate(UpdateText); 
                 this.Invoke(updateCallBack, new object[] { count }); 
             } 
             else 
             { 
                 lblTest.Text = count.ToString(); 
             } 
         } 
    
         void worker_DoWork(object sender, DoWorkEventArgs e) 
         {   
             /* Old Skool delegate usage.  See above for delegate and method definitions */ 
             for (int i = 0; i < 50; i++) 
             { 
                 UpdateText(i); 
                 Thread.Sleep(50); 
             } 
    
             // Anonymous Method 
             for (int i = 0; i < 50; i++) 
             { 
                 lblTest.Invoke((MethodInvoker)(delegate() 
                 { 
                     lblTest.Text = i.ToString(); 
                 })); 
                 Thread.Sleep(50); 
             } 
    
             /* Lambda using the new Func delegate. This lets us take in an int and 
              * return a string.  The last parameter is the return type. so 
              * So Func<int, string, double> would take in an int and a string 
              * and return a double.  count is our int parameter.*/ 
             Func<int, string> UpdateProgress = (count) => lblTest.Text = count.ToString(); 
             for (int i = 0; i < 50; i++) 
             { 
                 lblTest.Invoke(UpdateProgress, i); 
                 Thread.Sleep(50); 
             } 
    
             /* Finally we have a totally inline Lambda using the Action delegate 
              * Action is more or less the same as Func but it returns void. We could 
              * use it with parameters if we wanted to like this: 
              * Action<string> UpdateProgress = (count) => lblT…*/ 
             for (int i = 0; i < 50; i++) 
             { 
                 lblTest.Invoke((Action)(() => lblTest.Text = i.ToString())); 
                 Thread.Sleep(50); 
             } 
         }
    
    0 讨论(0)
  • 2020-12-12 11:15

    I assume that your question concerns c# and not .NET, because of the ambiguity of your question, as .NET does not get alone - that is, without c# - comprehension of delegates and lambda expressions.

    A (normal, in opposition to so called generic delegates, cf later) delegate should be seen as a kind of c++ typedef of a function pointer type, for instance in c++ :

    R (*thefunctionpointer) ( T ) ;
    

    typedef's the type thefunctionpointer which is the type of pointers to a function taking an object of type T and returning an object of type R. You would use it like this :

    thefunctionpointer = &thefunction ;
    R r = (*thefunctionpointer) ( t ) ; // where t is of type T
    

    where thefunction would be a function taking a T and returning an R.

    In c# you would go for

    delegate R thedelegate( T t ) ; // and yes, here the identifier t is needed
    

    and you would use it like this :

    thedelegate thedel = thefunction ;
    R r = thedel ( t ) ; // where t is of type T
    

    where thefunction would be a function taking a T and returning an R. This is for delegates, so called normal delegates.

    Now, you also have generic delegates in c#, which are delegates that are generic, i.e. that are "templated" so to speak, using thereby a c++ expression. They are defined like this :

    public delegate TResult Func<in T, out TResult>(T arg);
    

    And you can used them like this :

    Func<double, double> thefunctor = thefunction2; // call it a functor because it is
                                                    // really as a functor that you should
                                                    // "see" it
    double y = thefunctor(2.0);
    

    where thefunction2 is a function taking as argument and returning a double.

    Now imagine that instead of thefunction2 I would like to use a "function" that is nowhere defined for now, by a statement, and that I will never use later. Then c# allows us to use the expression of this function. By expression I mean the "mathematical" (or functional, to stick to programs) expression of it, for instance : to a double x I will associate the double x*x. In maths you write this using the "\mapsto" latex symbol. In c# the functional notation has been borrowed : =>. For instance :

    Func<double, double> thefunctor = ( (double x) => x * x ); // outer brackets are not
                                                               // mandatory
    

    (double x) => x * x is an expression. It is not a type, whereas delegates (generic or not) are.

    Morality ? At end, what is a delegate (resp. generic delegate), if not a function pointer type (resp. wrapped+smart+generic function pointer type), huh ? Something else ! See this and that.

    0 讨论(0)
提交回复
热议问题