web-dev-qa-db-fra.com

Puis-je utiliser des paramètres dans les délégués Action ou Func?

Lorsque j'essaie d'utiliser des paramètres dans un délégué Action ...

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

J'ai reçu cette erreur de temps de conception:

Jeton non valide 'params' dans la déclaration de la classe, de la structure ou de l'interface

De l'aide!

38
Homam

Que diriez-vous de cette solution de contournement?

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

Ou vous pouvez définir votre propre type de délégué:

delegate void LogAction(string s, params object[] args);
38
CodesInChaos

Les paramètres de type variadic ne sont pas possibles en C #.

C'est pourquoi il y a beaucoup de déclarations pour Action<...>, Func<...> et Tuple<...>, par exemple. Ce serait une fonctionnalité intéressante, cependant. C++ 0x les a .

11
Jordão

Tu pourrais essayer ça. Cela permet un nombre quelconque d'arguments, et vous obtiendrez une erreur de compilation si vous transmettez un nombre ou un type d'argument incorrect.

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));
6
Bryan Clark

Vous pouvez utiliser params dans la déclaration réelle d'un délégué, mais pas dans le type d'un. Les paramètres génériques d'une action sont uniquement des types, pas les arguments à transmettre lors de l'appel du délégué. params n'est pas un type, c'est un mot clé. 

3
Gordon Gustafson

J'ai fait une extension mineure du code ci-dessus à partir de Bryan, pour montrer comment envelopper plusieurs appels de méthode.
J'utilise ceci pour envelopper plusieurs méthodes contenant des appels de base de données dans une seule transaction.
Merci Bryan :-)
(Vous pouvez exécuter ce qui suit dans LINQPad pour tester) 

//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  
0
kamgman