简体   繁体   中英

How to return a generic function from a non-generic function?

This will probably be easiest to explain with an example.

So, let's start with the following TryNTimes function.

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

And use it like

MyType x = TryNTimes(DoSomething, 3);
MyOtherType y = TryNTimes(DoSomethingElse, 3);

But I'm using this in many cases with the same N , so I'd like to make it easy to create a function that injects the n value into here. So the use would be

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

The closest I could come up with was

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

But that's not really what I want, because it forces me to specify T a-priori, so it's not really reusable in the way that I want. I want to be able to delay the T , returning a generic function as a value. Something like

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

Is this something that's possible in C#?

workaround:

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

Use:

var tryThreeTimes = new RetryWrapper(3);
MyType x = tryThreeTimes.Try(DoSomething);
MyOtherType y = tryThreeTimes.Try(DoSomethingElse);
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;
                }
            }
        }
    }
}

Usage:

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

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM