Delphi 2009 에서 Generic이 추가되면서 유용한 클래스들이 추가되었다.
특히나 특정 Key와 쌍을 이루는 값을 저장할때 TDictionary는 참 유용하게 쓰인다.
일반 데이터 형을 보관할 때는 상관이 없으나 Class를 보관할때는 메모리 해제에 주의해야 한다.

uses
  Generics.Collections;

type
  TTempKey = class
  end;

  TTempValue = class
  end;

1. TDictionary
procedure TForm2.Button1Click(Sender: TObject);
var
  Dic: TDictionary<Integer,TTempValue>;
  Key: Integer;
begin
  Dic := TDictionary<Integer,TTempValue>.Create;
  try
    Dic.Add( 1, TTempValue.Create );

    for Key in Dic.Keys do
      Dic.Items[Key].Free;
  finally
    Dic.Free;
  end;
end;

Key와 매칭되는 Value를 저장할 수 있다.
여기서는 Key의 형을 Integer, Value의 형은 TTempValue 클래스로 설정했다.

Dic만 해제하면 TDictonary의 Values에 저장된 TTempValue 인스턴스가 붕 떠서 Memory Leak이 발생한다.
반드시 Dic를 해제하기 전에 Dic의 아이템들을 해제해야 한다.


2. TObjectDictionary

예전부터 Contnrs 유닛에 있던 TObjectList와 비슷하다.
생성시에 OwnsObject를 True로 설정해서 자동으로 아이템의 메모리를 해제했던 기억이 있을 것이다.

(1) Key와 Value 가 모두 Class형인 경우

procedure TForm2.Button2Click(Sender: TObject);
var
  Dic: TObjectDictionary<TTempKey,TTempValue>;
begin
  Dic := TObjectDictionary<TTempKey,TTempValue>.Create( [doOwnsKeys, doOwnsValues] );

  try
    Dic.Add( TTempKey.Create, TTempValue.Create );
  finally
    Dic.Free;
  end;
end;

인스턴스 생성시에 생성자의 인자를 보면 TDictionaryOwnerships라는 집합형을 넘긴다.
TObjectList의 OwnsObject를 생각하면 된다.
Key와 Value가 모두 클래스 형이므로 둘다 소유하는 것으로 설정했다.


(2) Value만 Class형인 경우

procedure TForm2.Button3Click(Sender: TObject);
var
  Dic: TObjectDictionary<Integer,TTempValue>;
begin
  Dic := TObjectDictionary<Integer,TTempValue>.Create( [doOwnsValues] );

  try
    Dic.Add( 1, TTempValue.Create );
  finally
    Dic.Free;
  end;
end;

Value만 클래스 형인 경우 Key를 소유하라고 doOwnsKeys를 설정하면 익셉션이 발생한다.
익셉션 클래스는 EInvalidCast, 메시지는 Invalid class typecast.

+ Recent posts