tags:

views:

151

answers:

2

I'm trying to make my own understandable example of what the method RelayCommand is doing in the following code:

return new RelayCommand(p => MessageBox.Show("It worked."));

the constructor is this:

public RelayCommand(Action<object> execute, Predicate<object> canExecute)
{
    if (execute == null)
        throw new ArgumentNullException("execute");

    _execute = execute;
    _canExecute = canExecute;
}

In my last question Jon Skeet pointed me in the right direction so I could get an example (below) that does what I wanted (pass some method name as in MessageBox.Show above). But the problem is, to get it to work, I had to take out all the lambda syntax (Action, Predicate, etc.), which is what I am trying to understand.

Is there a way to change the working example so it performs the same function but uses the lambda-syntax as a parameter as in the commented out lines below?

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

namespace TestLambda24
{
    class Program
    {
        static void Main(string[] args)
        {
            int[] numbers = { 6, 3, 7, 4, 8 };

            //Console.WriteLine("The addition result is {0}.", Tools.ProcessNumbers(p => Tools.AddNumbers, numbers));
            Console.WriteLine("The addition result is {0}.", Tools.ProcessNumbers(Tools.AddNumbers, numbers));

            //Console.WriteLine("The multiplication result is {0}.", Tools.ProcessNumbers(p => Tools.MultiplyNumbers, numbers));
            Console.WriteLine("The multiplication result is {0}.", Tools.ProcessNumbers(Tools.MultiplyNumbers, numbers));

            Console.ReadLine();
        }
    }

    class Tools
    {
        public static int ProcessNumbers(Func<int[], int> theMethod, int[] integers)
        {
            return theMethod(integers);
        }

        public static int AddNumbers(int[] numbers)
        {
            int result = 0;
            foreach (int i in numbers)
            {
                result += i;
            }
            return result;
        }

        public static int MultiplyNumbers(int[] numbers)
        {
            int result = 1;
            foreach (int i in numbers)
            {
                result *= i;
            }
            return result;
        }
    }

}
+2  A: 

Well, you could do:

static void Main(string[] args)
{
    int[] numbers = { 6, 3, 7, 4, 8 };

    Console.WriteLine("The addition result is {0}.",
        Tools.ProcessNumbers(p => Tools.AddNumbers(p), numbers));

    Console.WriteLine("The multiplication result is {0}.",
        Tools.ProcessNumbers(p => Tools.MultiplyNumbers(p), numbers));

    Console.ReadLine();
}

In other words, "given an array of numbers, call AddNumbers (or MultiplyNumbers) and pass in the array, and return the result".

It's pretty pointless to do that when you can just use the method group though.

Jon Skeet
A: 

What Jon said (surprise, surprise!)

The entire point of using lambdas is to create functions on the fly so you don't have to declare them statically. For instance,

Console.WriteLine("Mult value is {0}", Tools.ProcessNumbers(num => num.Aggregate(1, (i, j) => i*j), numbers));

Aggreagte() is an extension method that (for the overload I used) takes a seed value and a function.

It starts by saving the seed as an accumulator. Then, for each element in the series, it calls the given function with the current accumulator and the current value in the series, and stores the result in the accumulator (to be passed to the next element). The final returned value is returned as the overall result.

In other words, it does exactly the same thing as your hand-rolled versions, except it allows you to pass in both the initial value for 'result' as well as the code to be called inside the loop.

kyoryu