簡體   English   中英

Func<> 參數個數未知

[英]Func<> with unknown number of parameters

考慮以下偽代碼:

TResult Foo<TResult>(Func<T1, T2,...,Tn, TResult> f, params object[] args)
{
    TResult result = f(args);
    return result;
}

該函數接受具有未知數量的泛型參數和相應參數列表的Func<> 可以用C#寫嗎? 如何定義和調用Foo 我如何將args傳遞給f

那是不可能的。 充其量,您可以擁有一個也接受可變數量參數的委托,然后讓委托解析參數

TResult Foo<TResult>(Func<object[], TResult> f, params object[] args)
{
    TResult result = f(args);
    return result;
}


Foo<int>(args =>
{
    var name = args[0] as string;
    var age = (int) args[1];

    //...

    return age;
}, arg1, arg2, arg3);

您可以將DelegateDynamicInvoke一起使用。

這樣,您就不需要在f處理object[]了。

TResult Foo<TResult>(Delegate f, params object[] args)
{
    var result = f.DynamicInvoke(args);
    return (TResult)Convert.ChangeType(result, typeof(TResult));
}

用法:

Func<string, int, bool, bool> f = (name, age, active) =>
{
    if (name == "Jon" && age == 40 && active)
    {
        return true;
    }
    return false;
}; 

Foo<bool>(f,"Jon", 40, true);

我創建了一個顯示一些示例的小提琴: https : //dotnetfiddle.net/LdmOqo


筆記:

如果要使用method group ,則需要使用對Func的顯式轉換:

public static bool Method(string name, int age)
{
    ...
}
var method = (Func<string, int, bool>)Method;
Foo<bool>(method, "Jon", 40);

小提琴: https : //dotnetfiddle.net/3ZPLsY

使用 lambda 表達式可以很容易地做到這一點:

TResult Foo<Tresult>(Func<TResult> f)
{
  TResult result = f();
  return result;
}

然后用法可能是這樣的:

var result = Foo<int>(() => method(arg1, arg2, arg3));

其中method可以是返回int任意方法。

通過這種方式,您可以直接通過 lambda 傳遞任意數量的任何參數。

您可以嘗試類似於我在此處發布的內容: https : //stackoverflow.com/a/47556051/4681344

它將允許任意數量的參數,並強制執行它們的類型。

public delegate T ParamsAction<T>(params object[] args);

TResult Foo<TResult>(ParamsAction<TResult> f)
{
    TResult result = f();
    return result;
}

叫它,簡直……

Foo(args => MethodToCallback("Bar", 123));

在某些情況下,您可能可以使用這樣的技巧:

public static class MyClass
{
    private static T CommonWorkMethod<T>(Func<T> wishMultipleArgsFunc)
    {
        // ... do common preparation
        T returnValue = wishMultipleArgsFunc();
        // ... do common cleanup
        return returnValue;
    }

    public static int DoCommonWorkNoParams() => CommonWorkMethod<int>(ProduceIntWithNoParams);
    public static long DoCommonWorkWithLong(long p1) => CommonWorkMethod<long>(() => ProcessOneLong(p1));
    public static string DoCommonWorkWith2Params(int p1, long p2) => CommonWorkMethod<string>(() => ConvertToCollatedString(p1, p2));

    private static int ProduceIntWithNoParams() { return 5; }
}

盡管這並不是真正的要求,但一個簡單的解決方法是定義幾個具有不同類型參數數量的 Foo 方法。 具有超過 6 個參數的函數並不常見,因此可以定義以下方法並避開幾乎所有用例,同時保持類型安全。 然后可以將 Renan 的解決方案用於其余情況。

public TResult Foo<TResult> (Func<TResult> f)
{
    return f();
}

public TResult Foo<T1, TResult>(Func<T1, TResult> f, T1 t1)
{
    return f(t1);
}

public TResult Foo<T1, T2, TResult>(Func<T1, T2, TResult> f, T1 t1, T2 t2)
{
    return f(t1, t2);
}

...

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM