2013-08-16 37 views
7

Bir external package for storing graphs kullanıyorum. bir tepe ve bir kenar Türü:Şablonlar çıktısı alınmasına izin ver

var graph = new BidirectionalGraph<Vertex, Edge<Vertex>>(); 

Ne yazık ki, bu grafik paketi tek bir satır, bir tepe içine yayılan kenarları için izin vermeyen bir BidirectionalGraph iki şablon alır. Bunun yerine, sonuçlarla doldurulacak bir IEnumerable sağlamanız gerekir. Bu, "x vertex'in ardılları olan tüm köşelere geçiş yapmak" gibi görevler yaparak çok fazla kod alabilen iyi bir kodlama ritmini bozabilir.

Ben grafik sınıfına tek satırlık bir çözüm eklemek için .NET'in uzantılarını kullanmak istedi:

public static class GraphExtensions 
{ 
    public static IEnumerable<TEdge> IncomingEdges<TGraphSubtype, TVertex, TEdge>(this TGraphSubtype graph, TVertex n) 
     where TGraphSubtype : BidirectionalGraph<TVertex, TEdge> 
     where TEdge : IEdge<TVertex> 
    { 
     IEnumerable<TEdge> inputEdgesForVertex; 
     graph.TryGetInEdges(n, out inputEdgesForVertex); 
     return inputEdgesForVertex; 
    } 
} 

Ama nedense C# (.NET sürüm 4.5) için, graph.IncomingEdges(vertex) çağırdığınızda tahmin edemediği Şablon argümanları, bu yüzden şunu söylemeliyim:

graph.IncomingEdges<GraphThatInheritsFromBidirectionalGraph<VertexType,EdgeType>,VertexType,EdgeType>(vertex). Gerçekten büyük bir gelişme değil.

İlk, neden şablon türleri tahmin edilemiyor? Miras ile ilgili bir his var ama anlamıyorum. C++ kullanıyorum ve bazı sebeplerden dolayı gcc'nin şablon türlerini çıkarabileceğini hissediyorum.

İkinci, eğer bu önlenemezse, BidirectionalGraph'dan miras alınan gerçek kullanım için bir grafik sınıfı oluşturmak için doğru tasarım seçimidir? Kurucuları yeniden yazmak zorunda kalmak israf gibi görünüyor, ama eminim ki, açık şablon türleri ile yöntemin çağrılmasının uygun olmadığını kabul edersiniz.

DÜZENLEME:

Garip, eşdeğer özellikleri (aşağıda) yapar şablon türü otomatik çıkarsama sağlar. Yani, ilk problemimi çözse de (bu işlevi grafiğe eklemek), hala gerçekten anlamak isterim.

where TGraphSubtype : BidirectionalGraph<TVertex, TEdge> 

# derleyici yapmaz C: Bu tip kısıtından TEdge çıkarım gerektirecek gibi

public static class GraphExtensions 
{ 
     public static IEnumerable<TEdge> IncomingEdges<TVertex, TEdge>(this BidirectionalGraph<TVertex,TEdge> graph, TVertex n) 
      where TEdge : IEdge<TVertex> 
     { 
      IEnumerable<TEdge> inputEdgesForVertex; 
      graph.TryGetInEdges(n, out inputEdgesForVertex); 
      return inputEdgesForVertex; 
     } 
} 
+0

Derleyici hatası nedir? Grafik kütüphanesini indirmeden bunu yeniden üretmeye çalışıyorum .. ama şu ana kadar başarısız oldum :( –

+0

@SimonWhitehead "Hata 1 'MyDerivedGraph', 'IncomingEdges' ve hiçbir uzantı yöntemi için bir tanım içermiyor" IncomingEdges 'MyDerivedGraph' türünde bir ilk argümanı kabul etmek (bir kullanma yönergesini veya bir montaj referansını kaçırıyor musunuz?) bulunabilir, ancak şablon türlerini manuel olarak belirlediğimde, derler ve düzgün çalışır. (DÜZENLEYİCİ: Resharper yerleştirmeyi önerir < >, elle şablonlara koymam için yardım etmeye çalışıyorum) – user

cevap

1

Uzantınız yönteminin ilk sürümü, TGraphType ve TVertex ancak TEgde anlaması mümkün (tip kısıtlamalarından jenerik tip parametrelerini çıkarmaz). Bunun arkasında teknik bir neden olup olmadığını gerçekten bilmiyorum ya da uygulanmadı.

Güncellenmiş versiyonu, diğer taraftan, örneğin bir sınıf gibi uzantı yöntemini çağırdığınızda bu nedenle, bir parametre olarak BidirectionalGraph<TVertex, TEdge> içerir:

class AGraph: BidirectionalGraph<AVertex, AnEdge> { ... } 
... 
var aGraph = new AGraph(); 
aGraph.IncomingEdges(vertex); 

derleyici türünü incelemek yapabiliyor AGraph ve Devralma hiyerarşisinde benzersiz bir tür BidirectionalGraph<AVertex, AnEdge> olduğunu görebildiğinden, ve TEdge öğelerini bulabilir.

Not parametre türü olduğunu jenerik arabiriminin (yerine BidirectionalGraph<TVertex, TEdge> arasında) IGraph<TVertex, TEdge> ve AGraph uygulanan çoklu inşa tipleri, örneğin olsaydı o:

class AGraph: IGraph<AVertex, AnEdge>, 
       IGraph<AnotherVertex, AnotherEdge> { ... } 

o zaman söyleyemem çünkü bir kez daha başarısız olur çıkarım yazın Örneğin, TVertex, AVertex veya AnotherVertex'dur.

İlgili konular