调用具有可选参数的 Func<T1, T2, T3>?
Invoke Func<T1, T2, T3> which has optional parameters?
我有各种方法,它们有两个可选参数,一个 ConfigSourceType 枚举和一个表示文件路径的字符串,return "IConfigFile" 的一个实例(因配置文件而异)。
我试图将这些方法作为 Func 传递,以便我可以加载配置,但我无法调用不带参数的委托。如果我使用 Type.Missing,它仍然会抱怨缺少 ConfigSourceType 枚举。
编辑以包含代码:
数据处理器class:
public IConfigFile RetrieveMyConfiguration(
ConfigurationSourceType source = ConfigurationSourceType.Live,
string fileName = "")
{
/* Irrelevant */
return new ConfigFile();
}
主要:
private void SomeMethod()
{
var dHandler = new DataHandler();
MyConfig = LoadConfigFile(dHandler.RetrieveMyConfiguration);
}
public IConfigFile LoadConfigFile(
Func<ConfigurationSourceType, string, IConfigFile> func)
{
IConfigFile configFile;
// Line below doesn't compile:
configFile = func.Invoke(null, Type.Missing);
return configFile;
}
Delegates/Func 和方法是不同的东西。 Func 不能有可选参数;那只是方法的一个特征。
作为替代方案,您可以将所有参数放入 专用的 class、ConfigFileDescriptor
或其他内容中,并在构造函数中将参数设为可选。然后您可以使用 Func<ConfigFileDescriptor, IConfigFile>
。但是,由于需要创建对象,此解决方案需要输入更多内容。
Func中没有可选项
你必须把它包起来:
public class Foo
{
public int Boo(int A = 0, int B = 1)
{
return A + B;
}
}
var foo = new Foo();
var method = (Func<int, int, int>) (foo.Boo);
var methodWrapped = (Func<int, int, int>) ((a, b) => foo.Boo(a, b));
var methodWrappedWithA = (Func<int, int>) ((a)=>foo.Boo(a));
var methodWrappedWithB = (Func<int, int>)((b) => foo.Boo(B:b));
var methodWrappedNoAorB = (Func<int>) (()=>foo.Boo());
您不能为 Func<...>
指定可选参数,但您可以为自己的委托指定。
此 LINQPad 示例说明如何:
void Main()
{
var t = new Test(XYZ);
t();
t(15);
}
public delegate void Test(int a = 10);
public void XYZ(int a)
{
a.Dump();
}
输出:
10
15
然而,这意味着需要知道可选参数的是委托的接收端,但似乎您想为方法指定委托并在发送端指定可选参数,或者从您包装在委托中的方法中继承可选参数,除了创建匿名方法外,这是不可能的:
SomeMethod((a, b) => WrappedMethod(a, b, 42));
你可以这样做:
public delegate void MyDelegate(int a, int b, int? c = null, int? d = null);
public void Method(int a, int b, int c = 10, int d = 42) { ... }
new MyDelegate((a, b, c, d) =>
{
if (c.HasValue && d.HasValue)
Method(a, b, c.Value, d.Value);
else if (c.HasValue)
Method(a, b, c.Value);
else if (d.HasValue)
Method(a, b, d: d.Value);
else
Method(a, b);
});
但这开始变得荒谬了。
所以不,你真的不能轻易地做你想做的事。
我有各种方法,它们有两个可选参数,一个 ConfigSourceType 枚举和一个表示文件路径的字符串,return "IConfigFile" 的一个实例(因配置文件而异)。
我试图将这些方法作为 Func 传递,以便我可以加载配置,但我无法调用不带参数的委托。如果我使用 Type.Missing,它仍然会抱怨缺少 ConfigSourceType 枚举。
编辑以包含代码:
数据处理器class:
public IConfigFile RetrieveMyConfiguration(
ConfigurationSourceType source = ConfigurationSourceType.Live,
string fileName = "")
{
/* Irrelevant */
return new ConfigFile();
}
主要:
private void SomeMethod()
{
var dHandler = new DataHandler();
MyConfig = LoadConfigFile(dHandler.RetrieveMyConfiguration);
}
public IConfigFile LoadConfigFile(
Func<ConfigurationSourceType, string, IConfigFile> func)
{
IConfigFile configFile;
// Line below doesn't compile:
configFile = func.Invoke(null, Type.Missing);
return configFile;
}
Delegates/Func 和方法是不同的东西。 Func 不能有可选参数;那只是方法的一个特征。
作为替代方案,您可以将所有参数放入 专用的 class、ConfigFileDescriptor
或其他内容中,并在构造函数中将参数设为可选。然后您可以使用 Func<ConfigFileDescriptor, IConfigFile>
。但是,由于需要创建对象,此解决方案需要输入更多内容。
Func中没有可选项 你必须把它包起来:
public class Foo
{
public int Boo(int A = 0, int B = 1)
{
return A + B;
}
}
var foo = new Foo();
var method = (Func<int, int, int>) (foo.Boo);
var methodWrapped = (Func<int, int, int>) ((a, b) => foo.Boo(a, b));
var methodWrappedWithA = (Func<int, int>) ((a)=>foo.Boo(a));
var methodWrappedWithB = (Func<int, int>)((b) => foo.Boo(B:b));
var methodWrappedNoAorB = (Func<int>) (()=>foo.Boo());
您不能为 Func<...>
指定可选参数,但您可以为自己的委托指定。
此 LINQPad 示例说明如何:
void Main()
{
var t = new Test(XYZ);
t();
t(15);
}
public delegate void Test(int a = 10);
public void XYZ(int a)
{
a.Dump();
}
输出:
10
15
然而,这意味着需要知道可选参数的是委托的接收端,但似乎您想为方法指定委托并在发送端指定可选参数,或者从您包装在委托中的方法中继承可选参数,除了创建匿名方法外,这是不可能的:
SomeMethod((a, b) => WrappedMethod(a, b, 42));
你可以这样做:
public delegate void MyDelegate(int a, int b, int? c = null, int? d = null);
public void Method(int a, int b, int c = 10, int d = 42) { ... }
new MyDelegate((a, b, c, d) =>
{
if (c.HasValue && d.HasValue)
Method(a, b, c.Value, d.Value);
else if (c.HasValue)
Method(a, b, c.Value);
else if (d.HasValue)
Method(a, b, d: d.Value);
else
Method(a, b);
});
但这开始变得荒谬了。
所以不,你真的不能轻易地做你想做的事。