2017-01-17 1 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<string, TStringMap>(s3, s2, FPatientTypes)は何Iのうち、デルファイになるだろう、私は欠けているいくつかの呪文が、そこには約

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

を文句を言いながら、素朴な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>' 

を取得しますここでやろうとしてるの?

+0

これは一般的な方法を必要としていません。すでにジェネリック型をインスタンス化しています。質問内の最初のコードブロックで宣言した型エイリアスを使用します。 –

+0

@DavidHeffernanいいえ、私はすべての呼び出しを置き換えて、コンテナのコンテナのAddメソッドへの単一の識別子を持つことができます。私は自分自身に答えました、以下を参照してください。 – wades

+0

どうしてそれらのタイプを宣言しましたか? –

答えて

3

D'oh。

ジェネリックに2つの型パラメータのための必要はありません:(!面倒なキャストなし)

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

は書きやすいですし、何それが必要ありません。

+0

個人的には、クラスヘルパーとして代わりに、 'TDictionary 'クラス自体に新しいメソッドを追加しています。もし私が本当に "第二の価値を無視する"行動を必要とするならば。それ以外の場合は、READymadeストック '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

また、ループはここでの再帰より優れていると私は信じていますが、実際には味の問題です。 –

+1

@ Arioch'The正直言って、まずは愚かな考えです。ばかばかしい準複写キーの束を使ってデータセットを管理することの実用性は、再帰のかなり前に問題になるでしょう。 –

関連する問題