如何从非泛型函数返回泛型函数?

时间:2017-06-21 22:51:40

标签: c#

这可能是最简单的解释一个例子。

所以,让我们从以下TryNTimes函数开始。

public static T TryNTimes<T>(Func<T> f, int n)
{
    var i = 0;
    while (true)
    {
        try
        {
            return f();
        }
        catch
        {
            if (++i == n)
            {
                throw;
            }
        }
    }
}

并像

一样使用它
MyType x = TryNTimes(DoSomething, 3);
MyOtherType y = TryNTimes(DoSomethingElse, 3);

但是我在很多情况下都使用相同的N,所以我想创建一个将n值注入此处的函数。所以使用将是

var tryThreeTimes = CreateRetryWrapper(3);
MyType x = tryThreeTimes(DoSomething);
MyOtherType y = tryThreeTimes(DoSomethingElse);

我能想出的最接近的是

public static Func<Func<T>, T> CreateRetryWrapper<T>(int n)
{
    return f => TryNTimes(f, n);
}

但这并不是我想要的,因为它迫使我指定T a-priori,所以它不能以我想要的方式重复使用。我希望能够延迟T,将泛型函数作为值返回。像

这样的东西
public static Func<Func<_>, _> CreateRetryWrapper(int n)
{
    return f => TryNTimes(f, n);
}

这是C#中的可能吗?

2 个答案:

答案 0 :(得分:3)

解决方法:

class RetryWrapper 
{ 
    int n;
    public RetryWrapper(int _n) => n =_n;
    public T Try<T>(Func<T> f) => TryNTimes(f, n);
}

使用:

var tryThreeTimes = new RetryWrapper(3);
MyType x = tryThreeTimes.Try(DoSomething);
MyOtherType y = tryThreeTimes.Try(DoSomethingElse);

答案 1 :(得分:1)

class RetryWrapper
{
    readonly int n;

    private RetryWrapper(int n)
    {
        this.n = n;
    }

    public static RetryWrapper Create(int n)
    {
        return new RetryWrapper(n);
    }

    public T TryNTimes<T>(Func<T> f)
    {
        var i = 0;
        while (true)
        {
            try
            {
                return f();
            }
            catch
            {
                if (++i == n)
                {
                    throw;
                }
            }
        }
    }
}

用法:

RetryWrapper.Create(3).TryNTimes(() => 16);