调用具有可选参数的 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 不能有可选参数;那只是方法的一个特征。

作为替代方案,您可以将所有参数放入 专用的 classConfigFileDescriptor 或其他内容中,并在构造函数中将参数设为可选。然后您可以使用 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);
});

但这开始变得荒谬了。

所以不,你真的不能轻易地做你想做的事。