Hay montones de hilos de "debate sobre religion" acerca de Free vs FreeAndNil
Por ejemplo Nick Hodges da
algunas buenas razones para no usar FreeAndNil como una "receta magica que solucionara todos tus problemas"
Considera este ejemplo:
Código Delphi
[-]
procedure TForm3.Button1Click(Sender: TObject);
begin
if Query = NIL then begin
Query := TADOQuery.Create(NIL);
Query.Connection := ADOConnection;
end;
try
Query.SQL := '...' ;
Query.Open;
finally
Query.Free;
end;
end;
Obviamente falla, ya que como bien decis, al no haber asignado nil al puntero Query, si bien la memoria fue liberada, sigue apuntando a "quiensabedonde":
Query es distinto de NIL, entra en el bloque try-finally, y en la primer linea se rompe
No me gustaria proponer en ese caso "solucionarlo" con un FreeAndNil; porque si bien, el codigo va a funcionar, el problema es otro
1. Si se va a crear/destruir el query en cada ejecucion del metodo, porque esta declarado en la seccion private del Form? No seria mejor que este declarado local en el metodo? Mientras mas limitado el alcance de las variables, mejor
2. Si es necesario que este declarado como variable del Form porque se usa en otros metodos, porque hay que estar liberando la memoria en cada llamada al boton?
3. Osea que todo el codigo que use el objeto Query, va a tener que estar protegido con un chequeo contra NIL. Ahora bien, pregunto: Por que cuando se usa el TADOQuery soltando el componente en el Form no regamos el codigo con chequeos contra NIL?
No es mucho mas claro y sano ver esto?
Código Delphi
[-]
constructor TForm3.Create(AOwner: TComponent);
begin
inherited;
ADOConnection := TADOConnection.Create(NIL);
Query := TADOQuery.Create(NIL);
Query.Connection := ADOConnection;
end;
destructor TForm3.Destroy;
begin
ADOConnection.Free;
Query.Free;
inherited;
end;
procedure TForm3.Button1Click(Sender: TObject);
begin
if Query.Active then
Query.Close;
Query.SQL := '...' ;
Query.Open;
end;