2017-06-21 106 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);