2009-12-12 55 views
5

對不起,如果這是一個騙局,但我似乎無法得到正確的組合的關鍵字來過濾掉各種類型約束和泛型問題(因爲有很多)。非嚴格的多接口類型參數約束?

我有兩個接口 - 我們稱之爲IOnlineIOffline

他們密切相關,他們描述幾乎相同的合同,但他們之間的主要區別之一是具體實施將被使用的上下文。這不完全是我的情況,但它很好地說明了這個問題。

然後我有一些方法可以對付這些接口的具體實現者。有時這些方法只想處理一種類型而不處理另一種類型。

很簡單:

public void DoStuff<T>(string foo) where T : IOnline {} 

起腳正在實施,可以在任一類型的操作方法的代碼。我認爲這是正確的,但在閱讀編譯錯誤時,我期望該約束將被解釋爲「允許任何類型T在這裏通用,如果它們實現IOnline或IOffline」,實際上被解釋爲「允許任何類型T一般在這裏使用,如果他們實施兩個「。

public void DoStuff<T>(string foo) where T : IOnline, IOffline {} 

試圖執行具有相同名稱的兩種不同的方法,但由於有明顯的不確定性問題,不同的約束失敗 - 走,並非因爲超載參數列表是相同的(因爲所需的行爲是相同的)。

可以使用兩種不同的方法兩個不同的名字,每一個相應的約束,但似乎缺憾,使其他的事情下游是在屁股...可行的痛苦,但效果並不理想。

我覺得我必須有一些我在這裏失蹤的東西......我在普通的土地上感到非常舒適,但這是我第一次完成我所追求的事情,我覺得我'我正在旋轉我的輪子atm。

回答

8

在第二個示例中提供多個約束確實是可加的。 MSDN page on generic constraints有一點關於此。

你可以讓你的兩個接口從一個基本接口繼承,並將這些方法限制爲基本類型?

+0

說實話,我最近才知道C#支持接口繼承。在十年的開發工作中,這種需求從未出現過。將不得不給這個旋風,看看它是否最終讓我在我需要的地方。 – bakasan 2009-12-12 00:48:33

0

我認爲在.NET中執行此操作的標準方法是讓一個接口包含您的IOnline和IOffline函數,然後使用一些屬性來說明哪些函數實際在特定的類中實現。你可以在.NET的各個地方看到這種模式,例如Seek()方法,可能或可能不會實現,以及可以測試的CanSeek屬性。

這可能不是最乾淨的面向對象設計,但它的工作原理。

+0

另一種方法是定義單獨的IOnline和IOffline接口,以及一個繼承兩者的IOnlineAndOffline接口。該方法很好地工作,前提是實現IOnline和IOffline的類也實現IOnlineAndOffline。如果可能使用多種接口組合,那麼這種方法會變得有點麻煩。還有另一種方法可以在沒有組合爆炸的情況下擴展到任何數量的接口,但是它很糟糕。 – supercat 2010-12-18 02:40:37

+0

@supercat:我忘了我發佈了這個...一年後的零票!嗯,我想我會刪除它而不是修復它,但是感謝您的評論! – 2010-12-18 07:53:30

+0

我的確有興趣嘗試處理非分層接口的問題。看看http://stackoverflow.com/questions/4373259/storing-an-object-that-implements-multiple-interfaces-and-derives-from-a-certain這可能會花費我太多的時間在我的解決方法,而不是在這個問題上,讓我知道它是否有意義。 – supercat 2010-12-18 08:17:26

0

失去了一些編譯時檢查,但我看不到任何方式......你必須選擇你願意使用,(我假設你的喜好而定在線):

public void DoStuff<T>(string foo) 
{ 
    Type type = typeof(T); 
    if(type.GetInterfaces().Contains(typeof(IOnline))) 
     doStuffOnline<T>(foo); 
    else if(type.GetInterfaces().Contains(typeof(IOffline))) 
     doStuffOffline<T>(foo); 
    else 
     throw new Exception("T must implement either IOnline or IOffline"); 
} 

private void doStuffOnline<T>(string foo){ // can assume T : IOnline } 
private void doStuffOffline<T>(string foo){ // can assume T : IOffline } 
+0

不得不說,我同意其他人,雖然......更好的OOP方法來做到這一點,如單一的基礎接口... – LorenVS 2009-12-12 00:13:40

2

這也許不是一個回答你的問題,但我得到自發的,你可能想要的感覺重構你的接口。從你的問題:

他們密切相關的,因爲它們 描述幾乎相同的合同, 但 之間的主要區別是他們其中 具體實現將要使用的背景之一。

我對界面的看法是他們是合同。他們定義看起來應該如何,而不是應該如何表現;這是實施的任務。現在,我沒有關於您的應用程序或問題域的信息,但我可能會花費一些時間來識別這些接口的相同部分,並將它們移動到單個接口中,並且僅將這些差異保留爲單獨的接口。這樣你可以更輕鬆地瀏覽這些類型的問題。

+0

它歸結爲我的意圖 - 我已經看到接口作爲合同用作你描述,但我經常看到一個觀點,即一個接口,而一個契約,最終描述對象的行爲方式(作爲被所述契約約束的副作用)。 您的觀點雖然我們可能需要重構我們如何區分我們的兩種情境,但聽起來很可能。有更多微妙的原因,爲什麼我們想要接口,儘管...... doh! – bakasan 2009-12-12 00:47:24

相關問題