TDictionary i Assigned() - jak sprawdzić czy słownik jest utworzony

0

Mam taki oto kod operujący na słowniku

procedure DictionaryTest();
var dic : TDictionary<string, string>;
    s : string;
begin
dic := TDictionary<string, string>.Create();
try
  dic.Add('Klucz 1', 'Wartosc 1');
  dic.Add('Klucz 2', 'Wartosc 2');

  for s in dic.Keys do
    Writeln(Format('Klucz ze slownika: %s', [s]));

  for s in dic.Values do
    Writeln(Format('Wartosc ze slownika: %s', [s]));
finally
  if (Assigned(dic)) then dic.Free;
end;
end;

I moje pytanie jest następujące, jak sprawdzić czy zmienna typu TDictionary została zainicjalizowana.
Przykładowa poniższa procedura zgłasza AV:

procedure DictionaryTest2();
var dic : TDictionary<string, string>;
begin
//dic := TDictionary<string, string>.Create();
try
   //jakieś operacje na słowniku
finally
  if (Assigned(dic)) then dic.Free;
end;
end;

Pomoc dołączona do Delphi pisze:

Description
Tests for a nil (unassigned) pointer or procedural variable. 

Use Assigned to determine whether the pointer or procedure referenced by P is nil. P must be a variable reference of a pointer or procedural type. Assigned(P) corresponds to the test P<> nil for a pointer variable, and @P <> nil for a procedural variable. 

Assigned returns False if P is nil, True otherwise. 

Note:  Assigned cannot detect a dangling pointer--that is, one that is not nil but no longer points to valid data. For example, in the code example for Assigned, Assigned does not detect that P is not valid. 

Jest tu notka kiedy Assigned nie działa ale nie wiem co to jest "dangling pointer"

0

Assigned sprawdza, czy zmienna <> nil i jeśli nie to zwraca false. Zmienne lokalne w delphi mają to do siebie, że są inicjowane losową wartością (w przeciwieństwie do zmiennych globalnych, które są inicjowane wartościami domyślnymi - string - pusty ciąg, liczbowe na 0, obiekty na nil, itp). Więc nikt Ci nie zagwarantuje, że if Assigned(zmienna_lokalna) zachowa się tak jakbyś chciał ponieważ w chwili kompilacji nikt nie jest w stanie stwierdzić jaką wartość zmienna_lokalna będzie miała w tym ifie. Przypisz jej najpierw nil to będzie to działało. BTW kompilator nie krzyczał przypadkiem, że używasz niezainicjowanej zmiennej?

dangling pointer to zmienna, która jest <> nil ale nie wskazuje na poprawne miejsce w pamięci. Np. po zrobieniu free na obiekcie zmienna go wskazująca nadal ma wartość <> nil ale obiekt w pamięci już nie istnieje. Assign nie wyłapie takich przypadków. Poczytaj co robi FreeAndNill chociaż można się tego domyśleć z nazwy procedury

0

Dzięki abrakadaber za wyczerpującą odpowiedź.

Przeczytałem o FreeAndNill i patrząc po składni:

//FreeAndNil
procedure FreeAndNil(var Obj);
var 
  Temp: TObject;
begin 
  Temp := TObject(Obj); 
  Pointer(Obj) := nil; 
  Temp.Free;
end;

to procedura ta powinna nazywać się NilAndFree :)

Jeszcze raz dziękuję

1 użytkowników online, w tym zalogowanych: 0, gości: 1