2010-07-15 59 views
3

Phil Haack's attempt on null or empty coalescing的啓發,我試圖爲string對象以及IEnumerable<T>接口編寫幾個擴展方法來簡化無效或無效的ckecking。然而,我遇到了一些問題:當我試圖調用AsNullIsEmpty的版本時,編譯器將我的字符串視爲IEnumerable<char>,當然會給出錯誤的返回類型。對C#泛型的反約束

有沒有什麼辦法對的IEnumerable版本的定義把「反限制」,這樣我可以告訴編譯器使用一個每當T類型是string?像

public static IEnumerable<T> AsNullIfEmpty(this IEnumerable<T> items) 
    where T !: string 

東西,我知道我可以只改變其中一人的名字,但我想有一致性相同的名稱。

更新:原來我的問題與擴展方法解決了另一種方式,通過固定的簡單和愚蠢的錯誤(我用的是str.IsNullOrEmpty(),在IEnumerable<T>擴展方法,而不是string.IsNullOrEmpty(str) ...),但由於對泛型的反約束問題仍然是一個有趣的問題,我不會刪除它。

+0

編譯器將採取最具體的可用方法。如果你實現了一個字符串,並確保它可以在Call站點使用,那麼就不會有像描述的那樣的問題 – 2010-07-15 12:28:38

回答

8

要做到這一點的唯一方法是創建此擴展的重載,接受string作爲其this參數。

public static string AsNullIfEmpty(this string value) 

這樣做會導致特定類型的版本被認爲是比通用版本更好的過載匹配。

至於你的具體問題(「我能指定一個泛型類型參數的'反約束'嗎?」),答案是否定的。儘管如此,您可以非常接近Obsolete屬性。

[Obsolete("AsNullIfEmpty is not supported for strings.", true)] 
public static string AsNullIfEmpty(this string value) 

這將導致編譯器報告此超載的錯誤。

+0

這就是我的 - 正如你在我的更新中看到的,擴展方法問題已經解決。 (由於另一個錯誤而存在問題...)。但是,有什麼方法可以指定反約束? – 2010-07-15 12:28:30

+0

然後,當T是字符串時,您會得到具有相同簽名的2種方法的良好智能感知。 – 2010-07-15 12:29:05

+0

@Tomas:對此有一個簡單的答案:不,沒有辦法指定反約束。 – LukeH 2010-07-15 12:31:45