Могут ли params[] быть параметрами для лямбда-выражения?

Недавно я начал изучать лямбда-выражения, и возник вопрос. Скажем, у меня есть функция, которая требует неопределенного количества параметров. Я бы использовал ключевое слово params для моделирования этого переменного числа параметров.

Мой вопрос: могу ли я сделать что-то подобное с лямбда-выражениями? Например:

Func<int[], int> foo = (params numbers[]) =>
                       {
                           int result;

                           foreach(int number in numbers)
                           {
                               result += numbers;
                           }

                           return result;
                       }

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

3 ответа

Решение

Ну вроде как. Во-первых, вместо использования Func<>вам нужно будет определить пользовательский делегат:

public delegate int ParamsFunc (params int[] numbers);

Затем вы можете написать следующую лямбду:

ParamsFunc sum = p => p.Sum();

И вызвать его с переменным числом аргументов:

Console.WriteLine(sum(1, 2, 3));
Console.WriteLine(sum(1, 2, 3, 4));
Console.WriteLine(sum(1, 2, 3, 4, 5));

Но, если честно, гораздо проще придерживаться встроенного Func<> делегаты.

Самая близкая вещь, которую я думаю, что вы можете получить, будет что-то вроде этого:

Func<int[], int> foo = numbers[] =>
                       {
                           // logic...
                       }

var result = foo(Params.Get(1, 5, 4, 4, 36, 321, 21, 2, 0, -4));

И имеют:

public static class Params
{
    public static T[] Get(params T[] arr)
    {
        return arr;
    }
}

Но я не могу понять, как это лучше простого new[] {1, 5, 4, 4, ...}

Здесь есть две вещи, Func<int[], int> общий делегат на LHS и лямбда-выражение на RHS. Первое невозможно, так как Func<S, T> делегат объявлен как:

public delegate TResult Func<in T, out TResult>(T arg); //ie no params involved

Вам нужен собственный делегат, который принимает params введите, как показано в принятом ответе.

Последнее, о чем и идет заголовок вопроса, также невозможно в C#, но по причине.

LHS выражения присваивания - вещь времени компиляции (если это не dynamic конечно, но опять же, компилятор знает об этом), и его RHS - вещь времени выполнения (если, конечно, в случае const с). Компилятор может определить, что набрано в LHS, но он получает значения в RHS только во время выполнения, то есть при запуске кода. Когда вы печатаете это:

Func<int[], int> foo = ....

foo всегда считается Func<int[], int>, Это добавит много сложности компилятору, если он должен будет расшифровать RHS. Например, если то, что вы пытаетесь, было возможно, подумайте об этом сценарии:

Func<int[], int> foo = (params int[] numbers) =>
                   {
                       int result;

                       foreach(int number in numbers)
                       {
                           result += numbers;
                       }

                       return result;
                   };

//and later at some other place
foo = (int[] numbers) => 0;

//how would you call 'foo' now?

Вместо этого, когда вы пишете свой собственный делегат, который принимает params Вы говорите компилятору напрямую (то есть известно из LHS).

Из трех функций, которые поддерживают параметры именованного метода, т.е. out/ref, params, необязательный параметр, лямбда-выражения (или даже ранее delegate синтаксис) только поддержка out/ref,

Другие вопросы по тегам