2010-11-15 23 views
1

注:請重新標記和/或重新命名適當傳遞函數求<T, TResult>其中TResult未知


我有一個類,​​,一個包裝了Foo並實現IEnumerable<FooEnumerator>Foo表示樹形數據結構,枚舉的​​是當前節點的子節點。

Foo是供應商提供的數據對象。​​實現了一堆自定義過濾代碼。

class FooEnumerator : IEnumerable<FooEnumerator> 
{ 
    public Foo WrappedNode { get; private set; } 
    public string Name { get { return WrappedNode.Name; } } 
    public int Id { get{ return WrappedNode.Id; } } 
    public DateTime Created { get{ return WrappedNode.Created; } } 

    public FooEnumerator(Foo wrappedNode) 
    { 
     WrappedNode = wrappedNode; 
    } 

    public IEnumerator<FooEnumerator> GetEnumerator() 
    { 
      foreach (Foo child in this.GetChildren()) 
       if(FilteringLogicInHere(child)) 
        yield return new FooEnumerator(child); 
    } 

    ... 
} 

我希望能夠以這種表達向下傳遞給每一個新的枚舉項使用排序樹與給定(任意)的表達,創建頂級​​時定義的每個級別,並有。

我想使用lambda來定義排序表達式,就像使用OrderBy函數一樣。實際上,我打算將lambda傳遞給OrderBy

用於排序依據該signiture是

OrderBy<TSource, TKey>(Func<TSource, TKey> keySelector) 

其中TKey是給定Func的返回類型,但是在該方法中籤名的類型參數和在編譯時被計算出來。

示例用法

var x = GetStartingNode(); 

var sort = n => n.DateTime; 
var enu = new FooEnumerator(x, sort); 

var sort2 = n => n.Name; 
var enu2 = new FooEnumerator(x, sort2); 

排序表達式將被存儲在一個類變量和​​將工作等:

// pseudo-implementation 

private Expression<Func<Foo, TKey>> _sortBy; 

public FooEnumerator(Foo wrappedNode, Expression<Func<Foo, TKey>> sortBy) 
{ 
    WrappedNode = wrappedNode; 
    _sortBy = sortBy; 
} 

public IEnumerator<FooEnumerator> GetEnumerator() 
{ 
    foreach (Foo child in this.GetChildren().OrderBy(_sortBy)) 
     if(FilteringLogicInHere(child)) 
      yield return new FooEnumerator(child); 
} 

如何指定TKEY的類型(隱式或顯式地)在這個用例中?

我不想硬編碼它,因爲我希望能夠對底層Foo的任何和所有屬性進行排序。

回答

4

那麼,您不能創建類型爲Expression<Func<Foo,TKey>>的成員委託變量,因爲從未指定TKey。但是,您可以創建一個Expression<Func<Foo,IComparable>>類型的成員,這可能足以滿足您的需要。當然,您可能還需要更改構造函數以接受此簽名。

編輯:其他人建議參數化您的​​,以便它接受TKey。你當然可以這樣做,但你應該知道所出現的問題:

  1. 通過參數的枚舉,那麼你踢桶的道路。任何想要存儲FooEnumerator<T>的代碼都必須具有T類型的先驗知識。但是,您可以實施非通用接口IFooEnumerator來處理這個問題。
  2. 如果您希望支持將來在多個字段上進行排序,則參數化枚舉器會產生問題。 C#不支持具有可變數量類型參數的泛型,這限制了需要多個任意類型的泛型的創建。這個問題很難處理,因爲開始創建FooEnumerator<T>,FooEnumerator<T1,T2>,FooEnumerator<T1,T2,T3...>等是很尷尬的。
1

您也可以參數化的枚舉:

class FooEnumerator<TKey> { 

    // ... All your 'pseudo' code would work here 

} 

我建議對編程使用IComparable但是接口。

相關問題