2
 static uint Fibonacci(uint n)
    {
        return n <= 1 ? n : Fibonacci(n - 1) + Fibonacci(n - 2);
    }

Func<uint> fibN = () => Fibonacci(n);
Func<int, int, int> add = (a, b) => a + b;

I understand add function syntax: it returns int result of a + b statement into which int a and b parameters "goes".

But why fibN function has empty parameter block () ? Doesn't n "goes" to this function as parameter? Please help me to grasp some understanding of this moment.

2
  • You must be having some variable n accessible in the scope, where the declaration of fibN is placed Commented Feb 12, 2013 at 6:46
  • You probably have a static unsigned int in the scope of the method. Commented Feb 12, 2013 at 6:54

3 Answers 3

2

Your first lambda:

Func<uint> fibN = () => Fibonacci(n);

does not have any parameters. As it is now it will not compile since a variable n is necessary. This variable can either come from the lambda-parameters, or from the current scope. Since the lambda has no parameters, and no variable n from the current scope exist, it will not compile.

To make it compile, you could do the following:

uint n = 1; // Or any other value
Func<uint> fibN = () => Fibonacci(n);

Note: With lambas statement like your first lambda, you are depending on the current scope to execute them. The anonymous method that is compiled is therefore not static. Your second lambda statement on the other hand is not depending on the current scope (since all variables it uses are lambda-parameters), and this lambda is compiled into a static anonymous method. This might help you to understand how lambda statements are compiled. Basically lambda statements are compiled into normal anonymous methods.

Sign up to request clarification or add additional context in comments.

Comments

1

Consider the following code:

class Program
{
    static void Main(string[] args)
    {
        Func<uint> fibN = () => Fibonacci(n);
    }

    static uint Fibonacci(uint n)
    {
        return n <= 1 ? n : Fibonacci(n - 1) + Fibonacci(n - 2);
    }
}

It does not comile, as soon as there is no variable n of a suitable type to be used. However if you add:

uint n = 5;

into Main method or

static uint n = 5;

to the class, the code will compile.


Let's disassemble. For the following code:

static void Main(string[] args)
{
    uint n = 3;
    Func<uint> fibN = () => Fibonacci(n);
}

we get:

.method private hidebysig static void  Main(string[] args) cil managed
{
  .entrypoint
  .maxstack  3
  .locals init ([0] class [mscorlib]System.Func`1<uint32> fibN,
           [1] class Utils.Program/'<>c__DisplayClass1' 'CS$<>8__locals2')
  IL_0000:  newobj     instance void Utils.Program/'<>c__DisplayClass1'::.ctor()
  IL_0005:  stloc.1
  IL_0006:  nop
  IL_0007:  ldloc.1
  IL_0008:  ldc.i4.3
  IL_0009:  stfld      uint32 Utils.Program/'<>c__DisplayClass1'::n
  IL_000e:  ldloc.1
  IL_000f:  ldftn      instance uint32         Utils.Program/'<>c__DisplayClass1'::'<Main>b__0'()
  IL_0015:  newobj     instance void class [mscorlib]System.Func`1<uint32>::.ctor(object,
                                                                              native int)
  IL_001a:  stloc.0
  IL_001b:  nop
  IL_001c:  ret
} // end of method Program::Main

In this code you may find a hidden class c__DisplayClass1, in which we can see a public field of type uint32 named n:

.field public uint32 n

and method <Main>b__0:

.method public hidebysig instance uint32 
    '<Main>b__0'() cil managed
{
  .maxstack  1
  .locals init ([0] uint32 CS$1$0000)
  IL_0000:  ldarg.0
  IL_0001:  ldfld      uint32 Utils.Program/'<>c__DisplayClass1'::n
  IL_0006:  call       uint32 Utils.Program::Fibonacci(uint32)
  IL_000b:  stloc.0
  IL_000c:  br.s       IL_000e
  IL_000e:  ldloc.0
  IL_000f:  ret
} // end of method '<>c__DisplayClass1'::'<Main>b__0'

which actually calls Fibonacci and passes the n variable. So the compiler extracted the local variable n into a separate class; as well as extracted lambda into a method of this class. In the end it looks like you assign c__DisplayClass1.<Main>b__0 to Func<uint> fibN.

Comments

1

The function:

Func<uint> fibN = () => Fibonacci(n);

could be rewritten as the following, assuming n is a class variable:

private uint fibN() {
    return Fibonacci(n);
}

fibN therefore returns uint, but doesn't require an input parameter.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.