extension methods with generics - when does caller need to include type parameters?
Is there a rule for knowing when one has to pass the generic type parameters in the client code when calling an extension method?
So for example in the Program class why can I (a) not pass type parameters for top.AddNode(node), but where as later for the (b) top.AddRelationship line I have to pass them?
class Program
{
static void Main(string[] args)
{
// Cre开发者_开发问答ate Graph
var top = new TopologyImp<string>();
// Add Node
var node = new StringNode();
node.Name = "asdf";
var node2 = new StringNode();
node2.Name = "test child";
top.AddNode(node);
top.AddNode(node2);
top.AddRelationship<string, RelationshipsImp>(node,node2); // *** HERE ***
}
}
public static class TopologyExtns
{
public static void AddNode<T>(this ITopology<T> topIf, INode<T> node)
{
topIf.Nodes.Add(node.Key, node);
}
public static INode<T> FindNode<T>(this ITopology<T> topIf, T searchKey)
{
return topIf.Nodes[searchKey];
}
public static void AddRelationship<T,R>(this ITopology<T> topIf, INode<T> parentNode, INode<T> childNode)
where R : IRelationship<T>, new()
{
var rel = new R();
rel.Child = childNode;
rel.Parent = parentNode;
}
}
public class TopologyImp<T> : ITopology<T>
{
public Dictionary<T, INode<T>> Nodes { get; set; }
public TopologyImp()
{
Nodes = new Dictionary<T, INode<T>>();
}
}
With respect to the second example, the compiler does not know what type you want for R; it only knows that it must implement IRelationship<T>
and have a public default constructor. It can't infer it from any of the parameters you pass to the method because they are of type T. In that case, you need to tell it what class you want to be used for R. If you were to pass in, instead of create an instance of R, as an argument, it would be able to infer the type and you wouldn't need to supply them.
In the first case, you don't need to supply the types because the arguments are of the type and thus the compiler can infer the types that you mean.
Generally, you don't have to explicitly specify the type. You need it when the type is in fact an argument - and example to this is the linq function .Cast
- it's type tells it what to do: Cast<Employee>()
In your case this is quite simple: AddRelationship<T,R>
has three argumenta, all of type T
- how can R
be inferred?
I haven't done this particular setup, but my understanding of type inference is that the caller would not need to specify the type. this ITopology<T> topIf
will refer to an instance in which the type is already declared. The extension method should pick up the same type parameter implicitly.
A lot of the LINQ extension methods are based on generic extension methods of IEnumerable. It's the same pattern that you're using. That's a good place to start looking.
And as always, test.
I think it is because you do not include any argument with type R in the function.
精彩评论