Way back years ago I tried to understand delegates.
See the snippet how I did it.

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace Integrationproject
{
    // This is a delegate that points to a method taking a double and returning a double
    // in C this is something like      typedef double (*function)(double);
    // I know "function" is a reserved word in C...
    delegate double function(double x);

    class Program
    {
        class MyFunctions //all these have the same signature as my delegate
        {
            public double MyCubic(double x)
            {
                return x * x * x - 2 * x * x - x - 3;
            }

            public double MyLine(double x)
            {
                return 2 * x + 1;
            }

            public double Reciprocal(double x)
            {
                return 1/x;
            }
        }

        /////////////////////////////////////////////////////////////////////////////////////
        // Integrate a function by calculating the surface under a curve by using rectangles.
        // Just exercising the delegate functions here
        // Not a super way to do it, but it works in explaining delegates(I hope)
        // The higher the "parts" the better the integration.
        public static double IntegrateRect(double a, double b, int parts, function F)
        {
            double width = (b - a) / parts;
            double integral = 0.0;

            for (int i = 1; i <= parts; i++)
            {
                integral += width * F(a - 0.5 * width + i * width);
            }
            return integral;
        }

        static void Main(string[] args)
        {
            // make my class of functions come alive
            MyFunctions funcs = new MyFunctions();

            // integrate some functions between 1 and 2
            Console.WriteLine("Integrate linear function between 1 and 2:");
            // make f point to the MyLine function and pass it to IntegrateRect
            function f = new function(funcs.MyLine);
            Console.WriteLine(IntegrateRect(1.0, 2.0, 10, f));
            Console.WriteLine(IntegrateRect(1.0, 2.0, 1000, f));
            Console.WriteLine();

            //use the Reciprocal function here
            //insiders know this should be equal to ln(2)=0,6931471805599453094...
            //(natural logarithm)
            Console.WriteLine("Integrate reciprocal function between 1 and 2:");
            IntegrateRect(1.0,2.0,10,new function(funcs.Reciprocal));
            IntegrateRect(1.0, 2.0, 100, new function(funcs.Reciprocal));
            IntegrateRect(1.0, 2.0, 1000, new function(funcs.Reciprocal));
            Console.WriteLine();

            //sin has the same signature as our delegate so it should work
            Console.WriteLine("Integrate sine function between 1 and 2:");
            IntegrateRect(1.0,2.0,100,new function(Math.Sin));
        }
    }
}

OOPS! Did not notice up until now, that I am integrating like hell here, but I don't show the results to the console!
Please wrap every call to IntegrateRect in a Console.WriteLine as I did with the MyLine function but not with the others.
Sorry for the inconvenience.

The article starter has earned a lot of community kudos, and such articles offer a bounty for quality replies.