void Start( )
    {
        // create calculation objects that get chained to each other in a sec
        Chain calc1 = new AddNumbers();
        Chain calc2 = new SubstractNumbers();
        Chain calc3 = new DivideNumbers();
        Chain calc4 = new MultiplyNumbers();

        // now chain them to each other
        calc1.SetNextChain(calc2);
        calc2.SetNextChain(calc3);
        calc3.SetNextChain(calc4);

        // this is the request that will be passed to a chain object to let them figure out which calculation objects it the right for the request
        // the request is here the CalculationType enum we add. so we want this pair of numbers to be added
        Numbers myNumbers = new Numbers(3, 5, CalculationType.Add);

        calc1.Calculate(myNumbers);

        // another example:
        Numbers myOtherNumbers = new Numbers(6, 2, CalculationType.Multiply);

        calc1.Calculate(myOtherNumbers);

        // or pass it to some chain object inbetween which will not work in this case:
        Numbers myLastNumbers = new Numbers(12, 3, CalculationType.Substract);

        calc3.Calculate(myLastNumbers);
    }
        static void Main(string[] args)
        {
            //NO LAMBDA- no anonomus method- NAMED method
            int Sum(int x, int y)
            {
                return(x + y);
            }

            //przypisanie- dwie metody do wywołania
            //MyDelegate d = new MyDelegate(Sum);
            MyDelegate deletaTeSum = Sum;

            int result1 = deletaTeSum.Invoke(12, 15);

            Console.WriteLine("result 1:  " + result1);

            int result2 = deletaTeSum(12, 15);

            Console.WriteLine("result 2:  " + result2);


            void Execute()
            {
                //NO LAMBDA- anonomous method
                MultiplyNumbers multiply = delegate(int number1, int number2)
                {
                    return(number1 * number2);
                };

                //wykonanie
                Console.WriteLine("Anonomous method result- Execute:  " + multiply(4, 3) + "  " + multiply(4, 3).GetType());
            }

            Execute();

            //delegate, anonymous method using lambda, dynamic invoke (slow)
            MyIntAndString lambda = (int a, string b) => { Console.WriteLine("ELO: " + a + b); };

            //parameter is array of objects
            lambda.DynamicInvoke(new object[] { 123, "four five six" });


            //LAMBDA DELEGATES
            //  => GOES TO
            CombineTwoInts adder = (a, b) => { return(a + b); };

            Console.WriteLine("lambda delegate:  " + adder(3, 5));

            //LAMBDA DELEGATE
            CombineTwoInts multiplier = (int a, int b) => { return(a * b); };

            Console.WriteLine("lambda delegate2:  " + multiplier(3, 5));



            //LAMBDA PREDICATE
            var greaterThan3 = new List <int> {
                1, 2, 3, 4, 5, 6
            }.Where(x => x > 3);

            foreach (int i in greaterThan3)
            {
                Console.Write("Lambda in anonomoush method: " + i + ", ");
            }



            //Mosh lambda DELEGATE
            Func <int, int> square = number => number * number;

            Console.WriteLine(square(5));

            Console.ReadKey();
        }