我有一些数据类型:
type
TICD10CodeMap = TObjectDictionary<string, TICD10LookupResult>;
TStringMap = TDictionary<string, string>;
TFMRecMap = TDictionary<string, TFilemanRecord>;
他们的一些例子:
var
FICD10Codes: TICD10CodeMap;
FPatientTypes: TStringMap;
FPOVs: TFMRecMap;
FTreatmentTypes: TStringMap;
FTypesOfCare: TStringMap;
我有一个方法,使用他们的Add方法很愉快地填充它们,直到我发现我的数据源可能有重复的键。
现在我可以在每个Add()之前用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;
但似乎我对Delphi太聪明了。首先,在函数定义的主体中有一个强制转换,看起来它应该是不必要的,然后有一个事实,当我尝试调用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>'
是否有一些我想念的咒语,这会让Delphi脱离我想要做的事情?
答案 0 :(得分:3)
D'哦。
通用中不需要两个类型参数:
procedure AddPair<ValType>(Key: string; Val: ValType;
Dict: TDictionary<string, ValType>);
很容易写(没有麻烦的演员阵容!)并做了它应该做的事。
答案 1 :(得分: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.