2010-05-10 9 views
0

在調用擴展方法時,是否需要知道何時必須在客戶機代碼中傳遞泛型類型參數?帶泛型的擴展方法 - 調用者何時需要包含類型參數?

因此,例如在Program類中,爲什麼我可以(a)不傳遞top.AddNode(node)的類型參數,但後來爲(b)top.AddRelationship行我必須通過它們?

class Program 
{ 
    static void Main(string[] args) 
    { 
     // Create 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>>(); 
    } 
} 
+3

簡單的一個。當編譯器抱怨它無法推斷它時,你需要包含這個類型。 – Kobi 2010-05-10 11:31:03

回答

10

對於第二個例子,編譯器不知道你想要R的類型;它只知道它必須實現IRelationship<T>並且有一個公共的默認構造函數。它不能從你傳遞給方法的任何參數中推斷出它,因爲它們是T類型的。在這種情況下,你需要告訴它你想用於R的類。如果你要通過,創建一個R的實例,作爲一個參數,它將能夠推斷出類型,並且你不需要提供它們。

在第一種情況下,您不需要提供類型,因爲參數是類型的,因此編譯器可以推斷出您的意思。

+0

只是輸入相同的東西... – 2010-05-10 11:35:39

+0

謝謝,所以沒有辦法將我的庫提供給客戶端方法提供的客戶端用戶:(a)易於使用,無需指定類型;(b)基於擴展方法[即而不是抽象的基類擴展]呢?似乎沒有辦法? – Greg 2010-05-10 20:54:36

+0

@Greg - 可能讓您的拓撲界面包含一個(工廠)方法來從兩個INode創建關係。然後,您可以在擴展方法中使用工廠方法來創建適當的關係,而不需要爲方法提供類型。 – tvanfosson 2010-05-10 22:30:33

0

我還沒有做過這個特別的設置,但我對類型推斷的理解是調用者不需要指定類型。這個ITopology<T> topIf將引用已經聲明類型的實例。擴展方法應該隱式地選擇相同的類型參數。

很多LINQ擴展方法都基於IEnumerable的通用擴展方法。這與您使用的模式相同。這是一個開始尋找的好地方。

和往常一樣,測試。

0

我認爲這是因爲你沒有在函數中包含R類型的任何參數。

1

通常,您不必顯式指定類型。你需要它的時候的類型實際上是一個參數 - 和例子,這是LINQ功能.Cast - 它的類型告訴它做什麼:Cast<Employee>()

你的情況,這是很簡單的:AddRelationship<T,R>有三個argumenta,所有的鍵入T - 如何推斷R