具有可变数量的参数参数的匿名方法

时间:2016-02-02 20:59:46

标签: c# lambda anonymous-function func

我正在尝试创建一个带有参数的func的扩展方法。我想支持可变数量的参数(无,1,2,... 10)

我有类似的东西适用于三个参数。 如何简化它以支持可变数量的参数,而不必为每个排列复制和粘贴?它甚至可能吗?

(注意:我的示例非常简单。我的实际实现有更多逻辑,例如支持具有计数的'重试'逻辑,Thread.Sleep,跟踪日志记录,异常处理等。)

谢谢!

public static class UtilExtensions
{
    public static TResult Execute<T1, T2, T3, TResult>(Func<T1, T2, T3, TResult> function, T1 argument1, T2 argument2, T3 argument3))
    {
        // do other stuff ... like logging

        try
        {
           // call our 'action'
           TResult result = function(argument1, argument2, argument3);
           return result;
        }
        catch (Exception ex)
        {
           // do other stuff ... like logging, handle Retry logic, etc.
        }
    }
}

,它被调用如下:

public string DoSomething(int arg1, string arg2, MyObject arg3)
{
    if (arg1 == 1)
        throw new Exception("I threw an exception");

    return "I ran successfully";
}
public string DoSomethingElse()
{
    return "blah blah blah";
}

public string DoSomethingMore(DateTime dt)
{
    return "hi mom";
}


[TestMethod]
public void Should_call_UtilsExtensions_Execute_method_successfully()
{
    int p1 = 0;
    string p2 = "Hello";
    MyObject p3 = new MyObject();

    string results = UtilExtensions.Execute<int, string, MyObject, string>(
        DoSomething, p1, p2, p3);

    // ??? So how would I use my UtilExtensions api to call
    // DoSomethingElse (no arguments)
    // DoSomethingMore (one argument)
    // I'm okay to create overloads of my Execute method
    // but I don't want to copy-and-paste the same code/logic in each method

    results.Should().Be("I ran successfully");
}

2 个答案:

答案 0 :(得分:2)

我认为你不能这样做,据我所知,这正是Func和Action类型对.Net中不同参数号有许多不同声明的原因。请参阅https://msdn.microsoft.com/en-us/library/018hxwa8(v=vs.110).aspx

的左侧

你问的是类似的东西,除非在这种情况下OP询问接口Can I have a variable number of generic parameters?

问题基本上与仿制药的基本限制相同。

你可能能够用反射做一些事情,但我认为你最好选择合理数量的参数来支持和编写重载。

Params不起作用,因为对于params,数组中的所有类型都是相同的类型。 T1,T2等是不同类型供您使用。你必须将params声明为Object [],这完全违背了泛型。虽然你可能愿意放弃类型检查,如果你真的有一个未知数量的参数可能是不切实际的高。

答案 1 :(得分:1)

你不能这样做。另一种方法是创建一个接受一个参数的扩展方法,但该参数可以由匿名函数组成。因此,您的调用代码将完全控制如何使用它。不是最干净,但至少比代码生成器路径更清洁:

public static class UtilExtensions
{
    public static TResult Execute<TResult>(this Func<TResult> function)
    {
        // do logging

        try
        {
            TResult result = function();
            return result;
        }
        catch (Exception ex)
        {
            // do other stuff ... like logging, handle Retry logic, etc.
        }

        // or throw - this right here could prove unpredictable and is verrrry dirty
        return default(TResult);
    }
}

用法:

var param1 = 1;
var param2 = "string";

Func<bool> function = () => 
{
    // do stuff with param1 and param2
    return true;
}

var results = function.Execute();