2017-01-17 39 views
0

我有一些數據類型:是否有可能在Delphi中編寫這個泛型?

type 
    TICD10CodeMap = TObjectDictionary<string, TICD10LookupResult>; 
    TStringMap = TDictionary<string, string>; 
    TFMRecMap = TDictionary<string, TFilemanRecord>; 

而且他們的一些情況:

var 
    FICD10Codes: TICD10CodeMap; 
    FPatientTypes: TStringMap; 
    FPOVs: TFMRecMap; 
    FTreatmentTypes: TStringMap; 
    FTypesOfCare: TStringMap; 

而且我有一個方法,這是愉快地填充它們,使用它們的添加方法,直到我發現我的數據源可能有重複的鍵。

現在我可以只寫用的containsKey每個代碼之前,每添加(),並做一些事情,但我想我會是聰明的:

procedure AddPair<ValType, DictType: TDictionary<string, ValType>> 
    (Key: string; Val: ValType; 
    Dict: DictType); 
begin 
    if (Dict as TDictionary<string, ValType>).ContainsKey(Key) then 
    AddPair('Copy of ' + Key, Val, Dict) 
    else 
    Dict.Add(Key, Val); 
end; 

但似乎我對德爾福太聰明瞭。首先,在函數定義的主體中投射,看起來應該是不必要的,然後有一個事實,即當我嘗試調用AddPair時,會出現編譯器錯誤。天真AddPair(s3, s2, FPatientTypes)讓我既

[dcc32 Error] uReverseVistaLookups.pas(116): E2010 Incompatible types: 'ValType' and 'string' 
[dcc32 Error] uReverseVistaLookups.pas(116): E2010 Incompatible types: 'DictType' and 'System.Generics.Collections.TDictionary<System.string,System.string>' 

,而想成爲-更復雜AddPair<string, TStringMap>(s3, s2, FPatientTypes)抱怨

[dcc32 Error] uReverseVistaLookups.pas(127): E2515 Type parameter 'ValType' is not compatible with type 'System.Generics.Collections.TDictionary<System.string,System.string>' 

有一些咒語,我很想念,這將使德爾福出了什麼事情我試圖在這裏做?

+0

這似乎並不需要一個通用的方法。你已經實例化了泛型類型。使用在問題的第一個代碼塊中聲明的類型別名。 –

+0

@DavidHeffernan不,我想要一個單一的標識符,我可以將所有調用替換爲各種容器的添加方法。我已經回答了我自己,見下文。 – wades

+0

那你爲什麼要申報這些類型? –

回答

3

D'oh。

沒有必要在普通的雙類型參數:(!沒有麻煩投)

procedure AddPair<ValType>(Key: string; Val: ValType; 
    Dict: TDictionary<string, ValType>); 

很容易編寫和做什麼它應該。

+0

就我個人而言,我會作爲類助手來做,而不是將「添加」新方法添加到'TDictionary '類本身。如果我真的需要「忽略第二價值」行爲。否則,我只會使用現成的股票'TDictionary .AddOrSetValue'方法 –

+0

不,AddPair是一個包含字典的東西的方法。 – wades

1

雖然這看起來像是一種奇怪的方式來使用TDictionary,但獲得您想要的只是簡單的子類。

program Project1; 
{$APPTYPE CONSOLE} 
uses 
    Generics.Collections, SysUtils; 

type 
    TCopyKeyMap<TValue> = class(TDictionary<string, TValue>) 
    public 
     procedure AddWithCopy(const Key: string; const Value: TValue); 
    end; 
    TStringMap = TCopyKeyMap<string>; 

procedure TCopyKeyMap<TValue>.AddWithCopy(const Key: string; const Value: TValue); 
begin 
    if ContainsKey(Key) then 
    AddWithCopy('Copy of ' + Key, Value) 
    else 
    Add(Key, Value); 
end; 

var 
    sm : TStringMap; 
    sp : TPair<string, string>; 
begin 
    sm := TStringMap.Create; 
    try 
    sm.AddWithCopy('foo', 'bar'); 
    sm.AddWithCopy('foo', 'bat'); 
    sm.AddWithCopy('foo', 'bam'); 
    for sp in sm do WriteLn(Format('%s : %s', [sp.Key,sp.Value])); 
    finally 
    sm.Free; 
    end; 
    ReadLn; 
end. 
+0

子類....或者做一個類助手:-D –

+0

另外我相信while循環會比這裏的遞歸更好,不過這實際上是一個口味問題。 –

+1

@ Arioch'The這是一個愚蠢的想法開始,說實話。用一堆荒謬的準重複密鑰管理數據集的實用性在遞歸之前就已經成爲一個問題。 –

相關問題