Могу ли я использовать params в делегатах Action или Func? - PullRequest
38 голосов
/ 30 октября 2010

Когда я пытаюсь использовать params в делегате Action ...

private Action<string, params object[]> WriteToLogCallBack;

Я получил эту ошибку времени проектирования:

Недопустимые маркеры 'params' в объявлении члена класса, структуры или интерфейса

Любая помощь!

Ответы [ 5 ]

38 голосов
/ 30 октября 2010

Как насчет этого обходного пути?

private Action<string, object[]> writeToLogCallBack;
public void WriteToLogCallBack(string s, params object[] args)
{
  if(writeToLogCallBack!=null)
    writeToLogCallBack(s,args);
}

Или вы можете определить свой собственный тип делегата:

delegate void LogAction(string s, params object[] args);
11 голосов
/ 30 октября 2010

Параметры типа Variadic невозможны в C #.

Вот почему, например, существует множество объявлений для Action<...>, Func<...> и Tuple<...>. Это была бы интересная особенность. C ++ 0x имеет их .

6 голосов
/ 29 ноября 2017

Вы можете попробовать это. Он допускает любое количество аргументов, и вы получите ошибку времени компиляции, если передадите неверное число или тип аргументов.

public delegate T ParamsAction<T>(params object[] oArgs);

public static T LogAction<T>(string s, ParamsAction<T> oCallback)
{
    Log(s);
    T result = oCallback();
    return T;
}

Foo foo = LogAction<Foo>("Hello world.", aoArgs => GetFoo(1,"",'',1.1));
3 голосов
/ 30 октября 2010

Вы можете использовать params в фактическом объявлении делегата, но не в его типе.Общими параметрами для Action являются только типы, а не фактические аргументы, передаваемые при вызове делегата.params это не тип, это ключевое слово.

0 голосов
/ 23 августа 2018

Я сделал небольшое расширение для приведенного выше кода от Брайана, чтобы показать, как обернуть несколько вызовов методов.
Я использую это, чтобы обернуть несколько методов, содержащих вызовы базы данных, в одну транзакцию.
СпасибоБрайан: -)
(Вы можете запустить следующее в LINQPad для проверки)

//Wrapper code
public delegate void MyAction(params object[] objArgs);
public static void RunActions(params MyAction[] actnArgs)
{
    Console.WriteLine("WrapperBefore: Begin transaction code\n");
    actnArgs.ToList().ForEach( actn =>  actn() );
    Console.WriteLine("\nWrapperAfter: Commit transaction code");
}

//Methods being called
public void Hash  (string s, int i, int j)  => Console.WriteLine("   Hash-method call: " + s + "###" + i.ToString() + j.ToString());
public void Slash (int i, string s)         => Console.WriteLine("   Slash-method call: " + i.ToString()+ @"////" + s);

//Actual calling code
void Main()
{  
  RunActions( objArgs => Hash("One", 2, 1)
             ,objArgs => Slash(3, "four")   );
}

//Resulting output: 
// 
//  WrapperBefore: Begin transaction code
//  
//  Hash-method call: One###21
//  Slash-method call: 3////four
//  
//  WrapperAfter: Commit transaction code  
...