2013-08-16 30 views
7

Giả sử tôi đang sử dụng external package for storing graphs. Một BidirectionalGraph mất hai mẫu: một đỉnh và một loại cạnh:Cho phép mẫu được suy ra

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

Thật không may, đóng gói đồ thị này không cho phép bạn để có được các cạnh tỏa ra thành một đỉnh trong một dòng đơn. Thay vào đó, bạn phải cung cấp một số IEnumerable, nó sẽ điền với kết quả. Điều này có thể phá vỡ một nhịp điệu mã hóa tốt bằng cách thực hiện các nhiệm vụ như "vòng qua tất cả các đỉnh là những người kế thừa của đỉnh x" lấy quá nhiều mã.

Tôi muốn sử dụng phần mở rộng NET để thêm một giải pháp một dòng vào lớp đồ thị:

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; 
    } 
} 

Nhưng khi tôi gọi graph.IncomingEdges(vertex), vì một lý do C# (.NET phiên bản 4.5) không thể suy ra các đối số mẫu, vì vậy tôi phải nói:

graph.IncomingEdges<GraphThatInheritsFromBidirectionalGraph<VertexType,EdgeType>,VertexType,EdgeType>(vertex). Không thực sự là một cải tiến lớn.

Đầu tiên, tại sao các loại mẫu không thể ước tính? Tôi có cảm giác nó phải làm với thừa kế, nhưng không hiểu. Tôi đang sử dụng để sử dụng C + +, và đối với một số lý do cảm thấy rằng gcc có thể suy ra các loại mẫu.

Thứ hai, nếu điều này không thể ngăn chặn được, là lựa chọn thiết kế chính xác để tạo lớp biểu đồ để sử dụng thực tế, kế thừa từ BidirectionalGraph? Có vẻ như một sự lãng phí để phải viết lại các nhà xây dựng, nhưng tôi chắc chắn rằng bạn đồng ý rằng việc gọi phương thức với các kiểu mẫu rõ ràng là không phù hợp.

EDIT:

Kỳ lạ thay, các đặc điểm kỹ thuật tương đương (dưới đây) không phép suy luận tự động các loại mẫu. Vì vậy, mặc dù nó giải quyết vấn đề ban đầu của tôi (thêm chức năng này vào biểu đồ), tôi vẫn thực sự muốn hiểu.

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

Lỗi trình biên dịch là gì? Tôi đang cố gắng tái sản xuất này mà không cần tải xuống thư viện đồ họa .. nhưng cho đến nay tôi không thành công: ( –

+0

@SimonWhitehead Nó nói "Lỗi 1 'MyDerivedGraph' không chứa định nghĩa cho 'IncomingEdges' và không có phương pháp mở rộng 'IncomingEdges 'chấp nhận một đối số đầu tiên của loại' MyDerivedGraph 'có thể được tìm thấy (bạn đang thiếu một chỉ thị bằng cách sử dụng hoặc một tham chiếu lắp ráp?) ", nhưng khi tôi tự xác định các loại mẫu, nó biên dịch và chạy tốt. (EDIT: Resharper đề nghị chèn < >, cố gắng giúp tôi đặt mẫu theo cách thủ công) – user

Trả lời

1

Phiên bản đầu tiên của phương pháp mở rộng của bạn có thể suy ra TGraphTypeTVertex nhưng không TEgde, vì nó sẽ đòi hỏi suy luận ra TEdge từ loại chế:

where TGraphSubtype : BidirectionalGraph<TVertex, TEdge> 

mà biên dịch C# không làm (nó không suy ra các tham số kiểu generic từ các ràng buộc kiểu). Tôi thành thật không biết nếu có một lý do kỹ thuật đằng sau này hoặc nó chỉ không được thực hiện.

phiên bản cập nhật của bạn, mặt khác, bao gồm BidirectionalGraph<TVertex, TEdge> như một tham số, vì vậy ví dụ như khi bạn gọi phương thức mở rộng trên một lớp học như:

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

trình biên dịch có thể kiểm tra các loại AGraph và thấy rằng có một loại duy nhất BidirectionalGraph<AVertex, AnEdge> trong phân cấp thừa kế của nó, do đó, nó có thể suy ra TVertexTEdge.

Lưu ý rằng nếu loại tham số là IGraph<TVertex, TEdge> (thay vì BidirectionalGraph<TVertex, TEdge>) và AGraph thực hiện nhiều xây dựng các loại giao diện chung, ví dụ:

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

sau đó gõ suy luận sẽ thất bại một lần nữa bởi vì nó không thể nói nếu, ví dụ: TVertexAVertex hoặc AnotherVertex.

Các vấn đề liên quan