Возможно ли иметь C # лямбда / делегат, который может принимать переменное число параметров, которые могут быть вызваны с помощью Dynamic-invoke?
Все мои попытки использовать ключевое слово 'params' в этом контексте потерпели неудачу.
ОБНОВЛЕНИЕ С РАБОЧИМ КОДОМ ИЗ ОТВЕТ :
delegate void Foo(params string[] strings);
static void Main(string[] args)
{
Foo x = strings =>
{
foreach(string s in strings)
Console.WriteLine(s);
};
//Added to make it clear how this eventually is used :)
Delegate d = x;
d.DynamicInvoke(new[]{new string[]{"1", "2", "3"}});
}
Причина, по которой он не работает при прямой передаче аргументов в DynamicInvoke()
, заключается в том, что DynamicInvoke()
ожидает массив объектов, один элемент для каждого параметра целевого метода, и компилятор будет интерпретировать один массив как массив params для DynamicInvoke()
вместо одного аргумента целевого метода (если вы не преобразовать его в единый объект
).
Вы также можете вызвать DynamicInvoke()
, передав массив, содержащий массив параметров целевого метода. Внешний массив будет принят в качестве аргумента для единственного параметра params DynamicInvoke()
, а внутренний массив будет принят в качестве массива params для цели. метод.
delegate void ParamsDelegate(params object[] args);
static void Main()
{
ParamsDelegate paramsDelegate = x => Console.WriteLine(x.Length);
paramsDelegate(1,2,3); //output: "3"
paramsDelegate(); //output: "0"
paramsDelegate.DynamicInvoke((object) new object[]{1,2,3}); //output: "3"
paramsDelegate.DynamicInvoke((object) new object[]{}); //output: "0"
paramsDelegate.DynamicInvoke(new []{new object[]{1,2,3}}); //output: "3"
paramsDelegate.DynamicInvoke(new []{new object[]{}}); //output: "0"
}
Я чувствую, что есть очень важный момент, который здесь не обсуждается, и это если вы определили тип делегата, который принимает params
аргумент, нет особого смысла вообще вызывать для него DynamicInvoke
. Я могу себе представить единственный сценарий, в котором это вступит в игру, если у вас есть делегат вашего пользовательского типа, и вы передаете его в качестве параметра какому-то методу, который принимает Делегата
аргумент и вызывает DynamicInvoke
для этот.
Но давайте посмотрим на этот код в обновлении ОП:
delegate void Foo(params string[] strings);
static void Main(string[] args)
{
Foo x = strings =>
{
foreach(string s in strings)
Console.WriteLine(s);
};
x.DynamicInvoke(new[]{new string[]{"1", "2", "3"}});
}
Вышеприведенный вызов DynamicInvoke
совершенно лишний. Было бы гораздо разумнее, чтобы последняя строка читалась так:
x("1", "2", "3");
Нет, но любой из принимаемых параметров может быть массивом.
Без подробностей, на этом все.
Нет, но с небольшой помощью можно почти подделать:
object[] Params(params object[] args) { return args;}
// :
Action<string, object[]> CWL =
(format, args) => Console.WriteLine(format, args);
CWL("{0}, {1}", Params(1,2));