2009-12-07 63 views
3

我需要實現一個函數,它返回一個TDictionary,而不指定確切的類型。返回值可以是一個TDictionary<string,Integer>TDictionary<string,string>TDictionary<string,Boolean>在Delphi中安裝泛型是否安全?

難道我宣佈函數TDictionary作爲結果參數:

function GetMap: TDictionary; 

,然後將返回值:

type 
    TMyMapType: TDictionary<string,Integer>; 
var 
    MyMap: TMyMapType: 
begin 
... 
    MyMap := GetMap as TMyMapType; 
... 
end; 

編輯:發現似乎沒有辦法聲明與我的三種字典類型兼容的「通用」結果參數類型。

它看起來像我需要在Object Pascal語言像

type 
     TMyMapType: TDictionary<string, ?>; 

這是不(沒?)可能的。在Java中,它會是這樣的:

static Map<String, Integer>getIntegerMap() { 
    Map<String, Integer> result = new TreeMap<String, Integer>() {}; 
    result.put("foo", Integer.valueOf(42)); 
    return result;   
} 

static Map<String, ?> getMap() { 
    return getIntegerMap(); 
} 

public static void main(String[] args) { 
    System.out.println(getMap().get("foo")); 
} 

回答

2

沒有,沒有 「基地​​TDictionary類所有TDictionary版本的降臨」。參數類型是類類型的一部分。 TDictionary<T, U>的父類爲TEnumerable<TPair<T, U>>,其父類爲TObject

這有點煩人,但有必要保持類型安全。假設你有一個TDictionary<string, TMyObject>,並且你將它傳遞給一個函數,它的期望值爲TDictionary<string, TObject>。您可能會期望這起作用,因爲您可以將TMyObject傳遞給TObject參數。但事實並非如此,有一個很好的理由。

編譯器無法在編譯時檢查接收函數內部的實際類型,因此沒有任何東西阻止例程使用字典並調用.Add(Self.Name, Self),其中Self是TForm(或其他),而不是TMyObject 。由於所有對象引用的大小都是sizeof(指針),所以這看起來可以正常工作,但是當你知道第二個參數應該是什麼時,它會返回到代碼中,這是一個很大的問題。

通過對接收函數設置約束條件,有許多方法可以使泛型能夠像預期的那樣工作而不會破壞類型安全性,但是Delphi目前不實現它。德爾福棱鏡,並一直試圖讓德爾菲團隊在下一個版本中實現它,但我們必須看到...

+0

感謝您在閱讀本文和http://www.ibm.com/developerworks/java/library/j-jtp04298.html(其中顯示了使用'capture helpers'的可能解決方案'')之後,我理解了這個問題。在我的簡單情況下,具有原始包裝器對象的TDictionary 可能是一種解決方法,因爲我只需要它用於返回類型。 – mjn 2009-12-07 16:05:57

0

當調用GetMap時,您已經知道結果將是一個TDictionary。爲什麼不創建一個泛型函數GetMap of T和U,它返回T和U的TDictionary?

像這樣:

function GetMap<T, U>: TDictionary<T, U>; 

然後,你可以做到這一點沒有鑄造:

var 
    MyMap: TMyMapType; 
begin 
    MyMap := GetMap<string, integer>(); 
+0

函數GetMap :TDictionary ;不編譯 - 並且函數GetMap:TDictionary;也不會編譯。我現在再次在教程閱讀模式:) – mjn 2009-12-07 10:05:50

+1

這應該恕我直言工作得很好,如果'GetMap'是一個成員方法。 – jpfollenius 2009-12-07 20:56:04