2017-04-01 64 views
2

我今天在玩C#泛型和接口並試圖實現Graphs的經典定義。這是我最好的嘗試(做操只):C#中類聲明中泛型參數的重複

interface IVertex 
{ 
    string Name { get; set; } 
} 

interface IEdge<V> where V : IVertex 
{ 
    V From { get; set; } 
    V To { get; set; } 
} 

interface IGraph<V, E> where E: IEdge<V> where V: IVertex 
{ 
    IList<V> Vertices { get; } 
    IList<E> Edges { get; } 
} 

class Vertex : IVertex 
{ 
    public string Name { get; set; } 

    public Vertex(string name) 
    { 
     Name = name; 
    } 
} 

class Edge<V> : IEdge<V> where V: IVertex 
{ 
    public V From { get; set; } 
    public V To { get; set; } 

    public Edge(V from, V to) 
    { 
     From = from; 
     To = to; 
    } 
} 

class Graph<V, E> : IGraph<V, E> where E: IEdge<V> where V : IVertex 
{ 
    public IList<V> Vertices { get; } = new List<V>(); 
    public IList<E> Edges { get; } = new List<E>(); 
} 

但是我想,我做錯了什麼,因爲在以下用法:

var a = new Vertex("A"); 
var b = new Vertex("B"); 
var c = new Vertex("C"); 

var x = new Edge<Vertex>(a, b); 
var y = new Edge<Vertex>(b, c); 
var z = new Edge<Vertex>(c, a); 

var graph = new Graph<Vertex, Edge<Vertex>>() 
{ 
    Vertices = { a, b, c }, 
    Edges = {x, y, z} 
}; 

我需要指定通用參數Vertex (在線new Graph<Vertex, Edge<Vertex>>())兩次......

+0

這沒有什麼不妥(或者至少不是*本身*)。有什麼可以幫助的是寫'Edge:IEdge ',這樣通用參數就可以省略(所以在'Edge'類級別省略類型參數)。 –

+0

這是什麼問題? – Alejandro

+0

@Alejandro我認爲這個問題更多的是關於圖類的模板(或通用)專業化 – Everyone

回答

0

沒有更多的上下文,目前還不清楚你的約束和要求是什麼。但是,根據您要完成的操作,可能需要使用當前的語法,以確保您的IList<E>已被正確聲明。

也有可能您不要要求Graph類具有確切的IEdge<V>類型。如果是這樣,那麼你可以像這樣把它聲明:

class Graph<V> : IGraph<V, IEdge<V>> where V : IVertex 
{ 
    public IList<V> Vertices { get; } = new List<V>(); 
    public IList<IEdge<V>> Edges { get; } = new List<IEdge<V>>(); 
} 

在這種方法中,你將不能夠如將Edges分配給類型IList<E>的變量,其中EIEdge<V>以外的某種類型。例如,這是行不通的,而如果你需要這兩種類型中指定它的工作:

IList<Edge<Vertex>> list = graph.Edges; 

這一切都取決於你如何真正要使用這些類型。