←to practical programming

Note "delegates"

Delegates (pointers to functions)

In C-sharp a (pointer to a) function to be passed around is called a delegate. The consept of delegates has evolved substantially with time in Csharp and now the easiest way to work with delegates is to use the generic delegate System.Func (System.Action for functions that do not return anything). For example, the statement
System.Func<double,double> square = delegate(double x){return x*x;}
declares a variable square that references a function that takes a double argument and returns a double (in this particular case the square of its argument). The delegates can be used just as any other type in a C-sharp program. For example,
Func<double,double> f;
f=Sin;
double sin1 = f(1);
f=Cos;
double cos1 = f(1);
WriteLine($"sin(1)={sin1} cos(1)={cos1}");
	

Functions as arguments

You can pass around delegates just like any other objects in Csharp. For example, here is a funcion, make_table, that makes a table of values of a another function given as the argument to make_table,

static void make_table(Func<double,double> f){
	for(double x=0;x<10;x+=1)WriteLine($"{x} {f(x)}");
}

One can call make_table as

make_table(square);
make_table(Sin);

Anonymous delegates

Anonymous delegate is a delegate that is not bound to a variable. For example, we can make_table of the "square" function like this,
make_table( delegate(double x){return x*x;} );
There is syntactic sugar for anonymous delegates in C# called "lambda expressions" (like in Python). The previous call to make_table with a lambda expression would look like this,
make_table( (double x) => x*x );

Delegates with parameters

The variables in the declaration of a delegate are taken from the current scope as references and can then be used as extra parameters. For example,
double a=0;
Func<double> f = delegate(){ return a; };
WriteLine(f()); /* prints 0 */
a=7;
WriteLine(f()); /* prints 7 */
a=9;
WriteLine(f()); /* prints 9 */

Closures

If a function returns a delegate, then all the variables in the function scope are captured by value at the moment of return. The veriables from the enclosing scope are captured by reference. The returned object, a delegate with all the captured variables, is called a closure. For example,
public static Func<double> makefun(double a){
	Func<double> fun = delegate(){a++;return a;};
	return fun; /* "a" is captured here */
}