Can an anonymous method in C# call itself?

前端 未结 6 1899
-上瘾入骨i
-上瘾入骨i 2020-12-08 02:03

I have the following code:

class myClass
{
private delegate string myDelegate(Object bj);

protected void method()
   {
   myDelegate build = delegate(Object         


        
6条回答
  •  渐次进展
    2020-12-08 02:19

    Anonymous Recursion in C# has a terrific discussion on this topic.

    Recursion is beautiful and lambdas are the ultimate abstraction. But how can they be used together? Lambdas are anonymous functions and recursion requires names...

    Since this popped up again, here's an example of using the Y-combinator:

    // This is the combinator
    public static Func Y( Func, Func> f )
    {
        Func g = null;
        g = f( a => g(a) );
        return g;
    }
    

    Here's a usage of it to call an anonymous, recursive function ...

    Func exp = Y( e => x => ( x <=1 ) ? 1 : x * e( x - 1 ) );
    Console.WriteLine( exp(5) );
    

    You will note that if you do not use the Y-combinator and set up the recursion with just the delegate, you do not get correct recursion. For example ...

    // This is BAD. Do not do this!
    Func badRec = null;
    badRec = x => ( x <= 1 ) ? 1 : x * badRec( x - 1 );
    

    But everything works fine ...

    Console.WriteLine( badRec(5) );
    
    // Output
    // 120
    

    But try this ...

    Func badRec = null;
    badRec = x => ( x <= 1 ) ? 1 : x * badRec( x - 1 );
    
    Func badRecCopy = badRec;
    
    badRec = x => x + 1;
    
    Console.WriteLine( badRec(4) );
    Console.WriteLine( badRecCopy(5) );
    
    // Output
    // 5
    // 25
    

    What?!?

    You see, after the line badRec = x => x + 1;, the delegate you actually have is this ...

    badRecCopy = x => ( x <= 1 ) ? 1 : x * ( (x+1)-1 );
    

    So, badRec is incrementing the value by 1 which we expect (4+1=5), but badRecCopy is now actually returning the square of the value (5*( (5+1)-1 ) which we almost certainly did not expect.

    If you use the Y-combinator, it will work as expected ...

    Func goodRec = Y( exp => x => ( x <=1 ) ? 1 : x * exp( x - 1 ) );
    Func goodRecCopy = goodRec;
    

    And you get what you expect.

    goodRec = x => x + 1;
    
    Console.WriteLine( goodRec(4) );
    Console.WriteLine( goodRecCopy(5) );
    
    // Output
    // 5
    // 120
    

    You can read more about the Y-combinator (PDF Link).

提交回复
热议问题