Go4Expert

Go4Expert (http://www.go4expert.com/)
-   C# (http://www.go4expert.com/articles/c-sharp-tutorials/)
-   -   Nested Functions in C# (http://www.go4expert.com/articles/nested-functions-c-sharp-t3853/)

Sanskruti 13Apr2007 18:36

Nested Functions in C#
 
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: CSharp

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: CSharp

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: CSharp

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: CSharp

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: CSharp

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: CSharp

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.

rhaazy 24Jul2007 23:48

Re: Nested Functions in C#
 
Recurssion owns my mind, could you please explain recurssion alone, like I was a 12 year old or something?

sushovan.mukherjee 6Sep2007 02:22

Re: Nested Functions in C#
 
same as rhaazy

rekha11 31Jan2008 12:54

Re: Nested Functions in C#
 
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[i][0]);

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


All times are GMT +5.5. The time now is 15:16.