不能使用可变函数作为 Action 的参数 C#
Can't use variadic-function as Action's parameter C#
需要找到一种方法来传递具有 可变数量参数 的委托 Action(请参阅下面的 MyLog
)另一种方法(参见 MyLog
下面的 ExtractToDirectory
)。
我有一个日志方法:
public static void MyLog(string variable, params object[] args)
{
textBoxLog.AppendText(string.Format(message, args) + Environment.NewLine);
}
并在同一个 WinForm 中进一步调用 class:
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);
}
静态 class 方法:
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
的声明上。
params
关键字带有下划线并出现错误:Type expected.
我试着不放参数,但是 VS 需要一个对象数组而不是我需要的可变长度参数。
有线索吗?
删除 'params' 关键字并将其设为 Action<string, object[]>
,它可能会编译。 params
只是一个语法糖。函数本身不是 'variadic'。它只需要类型为 object[].
的第二个参数
当然,Action<string, object[]>
在所有情况下都将表现为非 'variadic',它希望您始终提供 new []{..}
。 Action/Func 代表不支持 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);
}
在 之后,我得到了这个:
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);
}
}
非常感谢您的帮助。
需要找到一种方法来传递具有 可变数量参数 的委托 Action(请参阅下面的 MyLog
)另一种方法(参见 MyLog
下面的 ExtractToDirectory
)。
我有一个日志方法:
public static void MyLog(string variable, params object[] args)
{
textBoxLog.AppendText(string.Format(message, args) + Environment.NewLine);
}
并在同一个 WinForm 中进一步调用 class:
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);
}
静态 class 方法:
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
的声明上。
params
关键字带有下划线并出现错误:Type expected.
我试着不放参数,但是 VS 需要一个对象数组而不是我需要的可变长度参数。
有线索吗?
删除 'params' 关键字并将其设为 Action<string, object[]>
,它可能会编译。 params
只是一个语法糖。函数本身不是 'variadic'。它只需要类型为 object[].
当然,Action<string, object[]>
在所有情况下都将表现为非 'variadic',它希望您始终提供 new []{..}
。 Action/Func 代表不支持 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);
}
在
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);
}
}
非常感谢您的帮助。