2010-07-05 65 views
3

所以我非常喜歡數據結構,並且我一直在研究以不同方式實現不同類型圖形的類庫。我遇到的絆腳石之一是試圖輕鬆地結合不同類型圖形的特定功能。爲了澄清,假設我有一個名爲IGraph <T>的接口,其中T是每個節點所擁有的數據。現在,我還想要具有IUndirectedGraph <T>,IDigraT >和IWeightedGraph < T,E >的接口,其中E是用作權重的類型。帶接口的C#類型聯盟

我希望能夠提供相同類型圖形的不同實現。例如,我希望能夠提供一個使用鄰接列表和使用鄰接矩陣的類的類。這些類可能具有某些算法的稍微不同的實現。作爲一個簡單的例子,確定給定對象的鄰居在每個實現中將是不同的。

所以,讓我們說我有這兩個類聲明:

class WeightedAdjacencyListGraph<T,E> : IUndirectedGraph<T>, IWeightedGraph<T,E> 

class WeightedAdjacencyMatrixGraph<T,E> : IUndirectedGraph<T>, IWeightedGraph<T,E> 

我想能夠聲明一個變量類型,可以存儲這兩個類的對象,但保持在定義的功能所有接口。基本上,我希望能夠來聲明一個變量類型,如:

<IUndirectedGraph<object>+IWeightedGraph<object,double>> MyGraph = new WeightedAdjacencyListGraph<object,double>(); 
MyGraph = new WeightedAdjacencyMatrixGraph<object,double>(); 

顯然,變量類型聲明是不正確的C#語法,但什麼我會放在這裏?我是否必須爲每個接口組合創建一個新接口?我的設計是否存在根本性缺陷?如果是這樣,我應該怎樣做才能糾正它?

編輯:我決定爲定向/無向圖創建不同的命名空間,並將常見接口(如IWeightedGraph < T,E >)存儲在根名稱空間中。然後,我將基本創建上面提到的組合界面(這些也在答案中註明)。我認爲無論如何,直接/無向圖在共享有趣的算法時不可能共享很多共同點。

回答

1

我想你可以創建一個接口,它是你想要的接口的組合。因此,在你的例子:

IComboGraph<T, E> : IUndirectedGraph<T>, IWeightedGraph<T,E> 

class WeightedAdjacencyListGraph<T,E> : IComboGraph<T, E> 

class WeightedAdjacencyMatrixGraph<T,E> : IComboGraph<T, E> 

然後用它作爲這樣:

IComboGraph<object, double> MyGraph = new WeightedAdjacencyListGraph<object,double>(); 
MyGraph = new WeightedAdjacencyMatrixGraph<object,double>(); 

編輯:我要補充一點,你的二合一接口並不一定有它的任何東西,但被定義爲那些繼承接口。

4

如果要規定,這兩項合同是爲了在一定情況下使用一種類型的實現,然後聲明既需要一個新的接口,並實施:

public interface IUndirectedAndWeightedGraph<T,E> : 
    IUndirectedGraph<T>, IWeightedGraph<T,E> 
{ 
} 

,將實現該任何類也履行個人合同,所以你仍然可以把任何實施了IUndirectedAndWeighted的課程當作IUndirected等。

你的理論方法在c#單一繼承多態性的背景下有着根本性的缺陷。該模型要求您將變量定義爲特定的單個「形狀」,並且只有明確(並非隱含)適合該形狀的對象可以放置在該變量中。使用dynamic可以允許某些類型的組合,但它有自己的權衡 - 也就是說,你失去了強類型和接口的好處。

0

您的設計對我來說似乎很合理,但不幸的是沒有明智的方式來實現您的需求。

  1. 爲所有組合創建接口是一個可能的解決方案,但如果您有三個,四個或更多接口,也是一個噩夢。

  2. 在C#4.0中,您可以使用dynamic。這花費了一些強大的靜態類型,可能還有一些性能 - 我也會盡量避免這種情況。

  3. 在可能的情況下,您可以使用具體類型或var以更緊密的耦合爲代價來簡化更改。

  4. 你也可以編寫一個包裝器來實現所有接口並將調用分派給一個被包裝的實例 - 也很討厭。

2

可以使用泛型爲此在的方法參數的有限的情況下和輸入約束:

void ProcessGraph<TGraph>(TGraph graph) 
    where TGraph: IUndirectedGraph<T>, IWeightedGraph<T,E> 
{ 
} 

美中不足的是,它與doesn't play nice方法重載。

但是,更一般地說,返回類型或變量沒有類似的東西。正如其他答案所指出的那樣,您必須明確定義「聯合接口」,並確保所有可以實現它的類都這樣做。如果所討論的所有接口都是你的接口,並且如果你沒有很多接口,這是一種可行的(如果單調乏味的)方法。