Say I'm using an external package for storing graphs. A BidirectionalGraph takes two templates: a vertex and an edge type:
var graph = new BidirectionalGraph<Vertex, Edge<Vertex>>(); Unfortunately, this graph package doesn't allow you to get the edges radiating into a vertex in a single line. Instead, you have to provide an IEnumerable, which it will populate with the results. This can disrupt a good coding rhythm by making tasks like "loop through all vertices that are successors of vertex x" take far too much code.
I wanted to use .NET's extensions to add a one-line solution to the graph class:
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; } } But when I call graph.IncomingEdges(vertex), for some reason C# (.NET version 4.5) can't infer the template arguments, so I have to say:
graph.IncomingEdges<GraphThatInheritsFromBidirectionalGraph<VertexType,EdgeType>,VertexType,EdgeType>(vertex). Not really a great improvement.
First, why can't the template types be estimated? I have a feeling it has to do with inheritance, but don't understand. I'm used to using C++, and for some reason feel that gcc could infer the template types.
Second, if this can't be prevented, is the correct design choice to make a graph class for actual use, which inherits from BidirectionalGraph? It seems a waste to have to rewrite the constructors, but I'm sure you'd agree that calling the method with explicit template types is inelegant.
EDIT:
Strangely, the equivalent specification (below) does allow automatic inference of template types. So, even though it solves my initial problem (adding this functionality to the graph), I'd still really like to understand.
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; } }