Передача параметров через Func‹›

Я использую делегаты с лямбда-выражениями вместо методов с одной строкой кода, например:

Func<int, int, int> Add = (x, y) => x + y;
int Result = Add(1, 2); // 3

Теперь у меня проблема, что мне нужно неизвестное количество параметров. Есть ли способ решить это следующим образом:

 Func<string, params string[], string> MergeFormat = (Look, values) => string.Format(Look, string.Join("-", values));

с params string[]

результат был бы

string.Format(func, string.Join("-", v1, v2, v3)); //currently
MergeFormat(func, v1, v2, v3); //new

person fubo    schedule 19.12.2014    source источник
comment
Мне не ясно, что именно вы пытаетесь сделать. Я подозреваю, что проблема может быть решена с помощью вашего собственного делегата, но если бы вы могли предоставить больше информации, вам было бы легче помочь.   -  person Jon Skeet    schedule 19.12.2014


Ответы (2)


params не является частью самого типа, поэтому вы не можете указать Func<string, params string[], string>. Но вы можете объявить своих собственных делегатов, похожих на Func, но имеющих массив параметров в качестве последнего параметра. Например:

using System;

delegate TResult ParamsFunc<T, TResult>(params T[] arg);
delegate TResult ParamsFunc<T1, T2, TResult>(T1 arg1, params T2[] arg2);
delegate TResult ParamsFunc<T1, T2, T3, TResult>(T1 arg1, T2 arg2, params T3[] arg3);
// etc        

class Program
{
    static void Main(string[] args)
    {
        ParamsFunc<string, string, string> func =
            (format, values) => string.Format(format, string.Join("-", values));

        string result = func("Look here: {0}", "a", "b", "c");
        Console.WriteLine(result);
    }
}
person Jon Skeet    schedule 19.12.2014
comment
Незаконно даже упоминать ключевое слово params в самой лямбде, т.е. изменение вашей стрелки на (string format, params string[] values) => string.Format(format, string.Join("-", values)); не будет компилироваться. - person Jeppe Stig Nielsen; 19.12.2014
comment
@JeppeStigNielsen: Да, и было бы смысла быть частью лямбды. Тем не менее, вполне логично, чтобы он был частью объявления делегата. - person Jon Skeet; 19.12.2014
comment
Я полагаю, вы правы. Ключевое слово преобразуется в ParamArrayAttribute в параметре. Это можно применить к сгенерированному методу (в который транслируется лямбда), но это мало поможет. При вызове func (вашего кода) мы не знаем, какие методы он содержит. Однако, если я сделаю лямбду с ref (я использую (ref int x) => { };) и еще одну с out, я увижу, что OutAttribute применяется к методу, созданному компилятором. - person Jeppe Stig Nielsen; 19.12.2014

Вы не можете сделать это таким образом, но есть обходное решение, которое вы можете использовать:

Если вы определяете свой Func таким образом:

Func<string[], string> FuncArray = (listOfStrings) => 
{
    // Here you can work on the listOfStrings, process it... 
    // and finaly you return a string from this method... 
}

Затем вы можете позже использовать этот FuncArray в других вызовах следующим образом:

public void MyMethod(Func<string[], string> delegateMethod, params string[] listOfString)
{
    if (delegateMethod != null)
    {
        string value = delegateMethod(listOfStrings);
    }

}

Таким образом, вы просто определяете Func‹>, который принимает массив строк в качестве параметра, а затем вы можете вызвать этот Func‹> из другого метода, который имеет параметр «params string[]».

person msporek    schedule 19.12.2014