1. This site uses cookies. By continuing to use this site, you are agreeing to our use of cookies. Learn More.

Nested Functions in C#

Discussion in 'C#' started by Sanskruti, Apr 13, 2007.

  1. Sanskruti

    Sanskruti New Member

    Joined:
    Jan 7, 2007
    Messages:
    108
    Likes Received:
    17
    Trophy Points:
    0
    Occupation:
    Software Consultant
    Location:
    Mumbai, India
    If you program in more than one language, sometimes you want to use an phrase or expression from one language in the other, when it does not exist you have to invent it for that language. Nested functions are functions defined within functions. They can be useful for compartmentalizing behavior that is invoked many times and at different places within a function. As well, they can be useful for naming a block of behavior within a function.

    To implement nested functions with parameters and return types, you need to know about delegates and another relatively new .NET capability, anonymous methods. Delegates and multi cast delegates in C# add some additional safety nets and capabilities, but delegate really is just a fancy name for function pointer and event handler.

    Now let us talk about calculating n! or n-factorial. The factorial algorithm takes a positive number n and returns 1*2*3*...n. For example, n! where n is 5 is 1*2*3*4*5 or 120. To map such a function by using a delegate signature, you can define a delegate that takes a long and returns a long, as follows:

    public delegate long FactorialDelegate(long n);

    The preceding defines a method signature, which permits you to define delegate instances that refer to methods matching this signature. The next thing you need to do is define an anonymous method inline where you define and initialize an instance of FactorialDelegate.

    Think of anonymous methods as similar to C++ inline methods. The real difference is that anonymous methods are function headers with code blocks but without names. (Anonymous methods are used mostly as values that are assigned to events; that is, they are inline event handlers.)To define an anonymous method, simply define a method whose header exactly matches the delegate signature but without the word delegate.

    Code:
    public static long Factorial(long n)
    {
       if (n < 1)
          throw new ArgumentOutOfRangeException("n", "argument must be greater than 0");
       long result = 1;
       for (int i = 1; i <= n; i++)
          result *= i;
       return result;
    }
    To convert the function Factorial to an anonymous method, you remove everything from the header except the parameter list (long n), add the word delegate, and leave the method body in place. The result looks like this:

    Code:
    delegate (long n)
    {
       if (n < 1)
          throw new ArgumentOutOfRangeException("n", "argument must be greater than 0");
          long result = 1;
          for (int i = 1; i <= n; i++)
             result *= i;
          return result;
    }
    Now, to nest this anonymous method, you can delcare an instance of FactorialDelegate and assign it the anonymous method above, as follows:
    Code:
    FactorialDelegate Factorial = delegate(long n)
    {
       if (n < 1)
          throw new ArgumentOutOfRangeException("n", "argument must be greater than 0");
          long result = 1;
          for (int i = 1; i <= n; i++)
             result *= i;
          return result;
    };

    Example 1 Containing nested functions


    Code:
    using System;
    using System.Collections.Generic;
    using System.Diagnostics;
    using System.Reflection;
    using System.Text;
    namespace NestedFunction
    {
       class Program
       {
          public delegate long FactorialDelegate(long n);
          static void Main(string[] args)
          {
           FactorialDelegate Factorial = delegate(long n)
              {
                if (n < 1)
                   throw new ArgumentOutOfRangeException("n", "argument must be greater than 0");
                long result = 1;
                for (int i = 1; i <= n; i++)
                   result *= i;
                return result;
             };
             Console.WriteLine( Factorial {0} is {1}", 5, Factorial1(5) );
             Console.ReadLine();
          }
       }
    }

    Recursion



    Factorial exists after it is defined. Hence, you cannot implement n! but using recursion. The recursive version using the very first Factorial algorithm would look like this:

    Code:
    public static long Factorial(long n)
    {
       return n > 1 ? n * Factorial(n - 1) : n;
    }
    Example 1 is having nested function, but cannot recurse by calling the variable Factorial. However, you can recurse by using reflection because even though the name Factorial doesn't exist in the anonymous method, the function does exist on the stack. Hence, all you need to do is pluck the Factorial method off the stack and call stack using reflection. Example 2 demonstrates how you can implement nested functions using recursion.

    Example 2: A Nested, Recursive Function Using Reflection



    Code:
    FactorialDelegate Factorial = delegate(long n)
    {
       if(n<1) throw  new  
       ArgumentOutOfRangeException("n", "argument must be greater than 0");
       MethodBase method = new StackTrace( ).GetFrame( 0 ).GetMethod( );
       return n  >  1  ?  n * (long)method.Invoke(null,new object[] { n - 1 }) : n;
    }
    The first half of the nested function in Example 2 is the same as in Example 1. To recurse, you need to pluck the method object off the stack; it will always be the first method entry in the stack frame. Because you also know the signature long—anonymous(long n), you can reliably invoke the method by passing the correct argument type and casting the return type.
     
  2. rhaazy

    rhaazy New Member

    Joined:
    Jul 6, 2007
    Messages:
    28
    Likes Received:
    0
    Trophy Points:
    0
    Recurssion owns my mind, could you please explain recurssion alone, like I was a 12 year old or something?
     
  3. sushovan.mukherjee

    sushovan.mukherjee New Member

    Joined:
    Sep 6, 2007
    Messages:
    8
    Likes Received:
    0
    Trophy Points:
    0
    Occupation:
    Student
    Location:
    Kolkata
  4. rekha11

    rekha11 New Member

    Joined:
    Jan 31, 2008
    Messages:
    13
    Likes Received:
    3
    Trophy Points:
    0
    The recursive nested functions are the name assigned to the delegate doesn't exist until after the anonymous delegate block. So, to recurs use reflection and pull the method right of the stack frame.
    this will be work like:

    public int getArrayValues(int i, int j)
    {

    if(j == 0)
    Console.writeln(array[0]);

    else
    {
    Console.writeln(array[j].toString());
    getArrayValues(i, j-1)
    }
    }
     

Share This Page