2015-10-13 47 views
1

我有一個通用的方法與無約束泛型類型。如果類型T實現接口,我需要獲取不同的IEqualityComparer。在C#中如何獲得不同的IEqualityComparer <T>實例如果泛型類型實現接口

一個代碼看起來大致是這樣的:

public SomeState MergeCollection<T>(
    ICollection<T> thisValue, 
    ICollection<T> otherValue, 
    SomeStrategy strategy = SomeStrategy.Default, 
    IEqualityComparer<T> comparer = null) 
{ 
    comparer = comparer ?? GetComparer<T>(strategy); 
    // code using comparer 
} 

public IEqualityComparer<T> GetComparer<T>(SomeStrategy strategy) 
{ 
    if(typeof(IMerge).IsAssignableFrom(typeof(T))) 
    { 
     return GetMergeComparer<T>(strategy); 
    } 
    else 
    { 
     return EqualityComparer<T>.Default; 
    } 
} 

似乎是模板專業化的典​​型案例尚未C#不支持這樣的功能,據我所知。我也在考慮實現一個策略模式的靜態類來交換抓取比較器的函數,但是靜態會爲所有類型實現,因此需要使用類型方法字典查找。爲此生成IL代碼似乎是最後的手段,考慮到代碼沒有被大量使用,不值得付出努力。

什麼是最好的方法來改變有問題的方法的行爲,所以如果T實現IMerge它會得到一個特殊情況?我問,因爲理論上應該可以在編譯時或至少在初始化時(靜態構造函數)定義行爲,如果它在運行時不會改變的話。

+4

你現有的代碼有什麼問題?雖然你可以在靜態的'ConditionalWeakDictionary'中緩存'typeof(IMerge).IsAssignableFrom(typeof(T)))',這不太可能是值得打擾的,並且可能不會提高性能。 – CodesInChaos

+0

我在最後添加了描述。它使用反射來改變編譯時已知的行爲,因此原則上它不被認爲是一個好的代碼。 – too

+0

每種類型一次似乎是一個很好的折衷。問題是類本身不是通用的,只是方法是。我想這將需要創建一個單獨的通用靜態比較器工廠類與抓住比較器的屬性。似乎艱難:) – too

回答

1
  1. 我不認爲你現有的代碼有什麼問題。就我個人而言,我會保持現狀。

    IMO在您有證據證明其性能至關重要之前對其進行優化是不成熟的優化。

  2. 如果你真的想緩存比較的結果,你可以使用類似:

    static class MergeComparerHelper<T> 
    { 
        static bool SupportsMerge = typeof(IMerge).IsAssignableFrom(typeof(T)); 
    } 
    

    它使用每個泛型實例都有自己的靜態字段的事實。你可以使用一個私有的嵌套類。

    但請注意,由於.NET JITter的當前實現不會爲不同的引用類型T s生成專門的實現,因此這仍然會導致運行時調度的成本。

+0

我會離開1,因爲它是,但2看起來像一個合理的做法,我一定會保持書籤更復雜/需要更多優化特殊類/方法專業化的特殊情況。它也顯示了C#在這個領域的侷限性。爲了以防萬一,我會等待接受幾天。感謝幫助。 – too

相關問題