不能将可变参数函数用作Action的参数C#

时间:2018-08-02 20:41:13

标签: c# delegates variadic-functions

需要找到一种方法,该方法将具有可变数量的参数(见下文MyLog)的委托动作传递给另一种方法(见{{1 }}放在ExtractToDirectory下面。

我有一个Log方法:

MyLog

然后在同一WinForm类中进一步调用:

public static void MyLog(string variable, params object[] args)
{
  textBoxLog.AppendText(string.Format(message, args) + Environment.NewLine);
}

带有方法的静态类:

private void buttonInstall_Click(object sender, EventArgs e)
{
  using (Stream zipStream = <Get stream from Resources>)
  using (ZipArchive zip = new ZipArchive(zipStream))
    zip.ExtractToDirectory(@"Z:\", MyLog);
}

问题出在public static class ZipFileExtensions { public static void ExtractToDirectory(this ZipArchive source, string destinationDirectoryName, Action<string, params object[]> myLog) { myLog("Starting {0} extraction", source.Name); } } 的声明上。 ExtractToDirectory关键字带有下划线并带有错误:期望的类型

我试图不放置参数,但是VS期望对象数组而不是我需要的可变长度参数。

有任何线索吗?

2 个答案:

答案 0 :(得分:2)

删除“ params”关键字并将其设置为Action<string, object[]>,它可能会编译。 params只是语法糖。函数本身不是“可变的”。它只是采用object []类型的第二个参数。

当然,Action<string, object[]>出于所有目的都不会表现为“杂色性”,它将希望您始终提供new []{..}。动作/功能委托不支持params。不过,您可以创建自己的专业代表:

using System;

public delegate void LogAction(string template, params object[] args);

public static void Log(string a, params object[] args)
{
    System.Console.WriteLine(a,args);
}

public static void Main()
{
    var act = new Action<string,object[]>(Test.Log);
    act("fooo {0} {3}", new object[]{1, 3, 4, 5});

    var myAct = new LogAction(Test.Log);
    myAct("fooo {0} {3}", 1, 3, 4, 5);
}

答案 1 :(得分:0)

quetzalcoatl answer之后,我结束了:


public partial class MainForm : Form
{
  public delegate void LogAction(string message, params object[] args);
  public void Logger(string message, params object[] args)
  {
    if (args != null)
      textBoxLog.AppendText(string.Format(message, args) + Environment.NewLine);
    else
      textBoxLog.AppendText(message + Environment.NewLine);
    Application.DoEvents();
  }

  private void buttonInstall_Click(object sender, EventArgs e)
  {
    Logger("Button clicked");
    using (Stream zipStream = Assembly.GetExecutingAssembly().GetManifestResourceStream(MethodBase.GetCurrentMethod().DeclaringType.Namespace + ".Resources.test.zip"))
    using (ZipArchive zip = new ZipArchive(zipStream))
      zip.ExtractToDirectory(Program.DestinationInstallation, Logger);
}

public static class ZipFileExtensions
{
  public static void ExtractToDirectory(this ZipArchive source, string destinationDirectoryName, MainForm.LogAction myLogger)
  {
    int number = 20180803;
    myLogger("{0} >> {1} (ok)", DateTime.Now, number);
  }
}

非常感谢您的帮助。