2017-06-21 129 views
1

这可能会最容易解释一个例子。如何从非泛型函数返回泛型函数?

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

​​

而且使用它像

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先验,所以它不是真的以我想要的方式重复使用。我希望能够延迟T,将泛型函数作为值返回。像

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

事情是这样的东西在C#中的可能吗?

+2

为什么不是一类'RetryWrapper',在至极的'TryNTimes'功能是成员,而n是财产?这可能是对这个问题的回避,但这就是我认为OOP/ – dovid

+0

@ lomed的正确方法。好的解决方法。我认为答案是否定的,C#不允许通用值或其他东西。所以这将是一个很好的选择。 –

回答

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); 
+0

任何想法为什么你需要一个“对象”,而不仅仅是一个函数? –

+0

@DaxFohl我不知道我理解你,但我会回答你一个问题:何时应该使用对象? – dovid

+0

那么,根据这个问题,我正在寻找一种方法来从普通的非泛型函数中返回一个普通的泛型函数。但是看起来在C#中没有像通用_value_这样的东西,所以无论如何都没有办法将该返回值分配给任何东西。所以这似乎是最好的解决方法。 –

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);