Как заставить этот рабочий пример примера делегатов передавать синтаксис лямбда в качестве параметра?

Я пытаюсь сделать свой понятный пример того, что делает метод RelayCommand в следующем коде:

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

конструктор такой:

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

    _execute = execute;
    _canExecute = canExecute;
}

В мой последний вопрос Джон Скит указал мне правильное направление, чтобы я мог получить пример (ниже), который делает то, что я хотел (передать имя метода, как в MessageBox.Show выше). Но проблема в том, чтобы заставить его работать, мне пришлось убрать весь лямбда-синтаксис (Действие, Предикат и т. д.), что я и пытаюсь понять.

Есть ли способ изменить рабочий пример, чтобы он выполнял ту же функцию, но использовал лямбда-синтаксис в качестве параметра, как в закомментированных строках ниже?

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;
        }
    }

}

person Edward Tanguay    schedule 16.04.2009    source источник


Ответы (2)


Ну, вы могли бы сделать:

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();
}

Другими словами, «имея массив чисел, вызовите AddNumbers (или MultiplyNumbers), передайте массив и верните результат».

Однако делать это довольно бессмысленно, когда вы можете просто использовать группу методов.

person Jon Skeet    schedule 16.04.2009

Что сказал Джон (сюрприз, сюрприз!)

Весь смысл использования лямбда-выражений заключается в создании функций на лету, чтобы вам не приходилось объявлять их статически. Например,

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

Aggreagte() — это метод расширения, который (для перегрузки, которую я использовал) принимает начальное значение и функцию.

Он начинается с сохранения семени в качестве аккумулятора. Затем для каждого элемента в ряду вызывается заданная функция с текущим аккумулятором и текущим значением в ряду и сохраняется результат в аккумуляторе (для передачи следующему элементу). Окончательное возвращаемое значение возвращается как общий результат.

Другими словами, он делает точно то же самое, что и ваши ручные версии, за исключением того, что он позволяет вам передавать как начальное значение для 'result', так и код, который будет вызываться внутри цикла. .

person kyoryu    schedule 06.08.2009