Pregunta

Tengo una pregunta general acerca de las mejores prácticas en OO Delphi. Actualmente, puse try-finalmente se hace en cualquier lugar se crea un objeto de liberar a ese objeto después de su uso (para evitar pérdidas de memoria). Por ejemplo:.

aObject := TObject.Create;
try
  aOBject.AProcedure();
  ...
finally
  aObject.Free;
end;

en lugar de:

aObject := TObject.Create;
aObject.AProcedure();
..
aObject.Free;

¿Cree que es una buena práctica, o demasiado trabajo? Y qué pasa con el rendimiento?

¿Fue útil?

Solución

En mi opinión, no hay más que una de las razones de una construcción se opone no debe seguido por ( o "en" como Mason señaló ) un bloque try / finally.

  1. Si toda la vida An objetos está siendo gestionado por otro objeto.

Esta dirección puede tomar tres formas:

  1. referencia de un objeto tiene un alcance más allá del bloque local y se libera otra parte -. Como un miembro campo liberado en el destructor
  2. Un objeto añadió inmediatamente a una lista que está a cargo de liberar el objeto más tarde.
  3. Un objeto con un gestor de toda la vida asociada, como la forma en que pase el propietario a un control de VCL en la construcción.

# 1 , cuando la referencia tiene un alcance más amplio , la referencia debe regularse a cero inmediatamente si no se construye de inmediato. De esta forma cuando se comprueba para referencia usted sabe que tiene una lectura precisa. Esto es más común con objetos miembro que se construyen como parte de una clase más grande, y luego se limpia cuando el objeto padre se destruye.

# 2 , cuando se añade un objeto a una lista , desea utilizar un bloque try-except (una de las pocas veces que uso uno) por si acaso se produce una excepción después de que el objeto se construye y antes de que se añade a la lista de gestión. Lo ideal sería que la primera línea después de la construcción es la adición a la lista, o la lista es en realidad una clase de fábrica que le da un objeto ya añadido a la lista.

# 3 , cuando un objeto tiene otro gestor de toda la vida , que realmente debería asegurarse de que la maneje que el manager es lo que hay que hacer. Si usted está construyendo un control de VCL, puede tener la tentación de tener la forma (o cualquier otro control) poseer, pero que en realidad pone una sobrecarga adicional en la construcción y destrucción. Si es posible, debería liberar explícitamente, esto es especialmente cierto si usted pone el control de una vez, entonces usted sabe que va a liberarlo en destructor de su forma o cuando se cierra. La única vez que no se puede hacer esto es si la creación de control es más dinámico.

Así que sí, es una buena práctica de utilizar una gran cantidad de bloques try / finally. Sólo debe tener unos cuantos bloques try / except, y la mayoría de ellas deberían tipos de excepción trampa muy específicas, y / o volver a subir la excepción. Si usted tiene más try / except que los bloques try / finally, entonces lo está haciendo mal .

Otros consejos

Es sin duda la mejor práctica con el uso de try-finally.

En el caso de una excepción, habiendo resucitado, ese objeto liberarse.

En cuanto a rendimiento:. medida antes de optimizar

Como Frank dijo: "En cuanto a rendimiento: medida antes de optimizar." Repitiéndolo para enfatizar.

Además, si va a crear un montón de objetos en un método, no es necesario utilizar un bloque try..finally para cada uno de ellos. Eso puede conducir a un desastre muesca feo. create, try, create, try, create, try, do something, finally, free, finally, free, finally, free. Uf! En su lugar, puede establecer las referencias a objetos a nil en la parte superior del método, a continuación, crear todos ellos, hacer un bloque try, y liberar a todos en la sección fin.

Esto ahorrará algo de sobrecarga y el rendimiento, (aunque es probable que nunca se nota la diferencia,) pero lo más importante que va a hacer el código más limpio y más fácil de leer mientras se mantiene el mismo nivel de seguridad.

Para responder a la segunda parte de su pregunta:
try finally apenas tiene ningún tipo de gastos.

De hecho, hay un montón de métodos que tienen un intento implícito ... finally. Por ejemplo sólo tener una función usando una var de cualquier tipo de interfaz y la asignación de un valor que tiene.

- Jeroen

El año pasado en Delphi días Desarrollador vi algunos de alijo privado de Marco Cantú de código y que él llama finalmente probar cada vez que crea nada.

Alguien le preguntó al respecto, y dijo que intenta hacerlo todo el tiempo.

Pero es sobre todo una buena idea por un código multiproceso cuando se trata de entrar y salir de las secciones críticas, aunque eso no es sobre el tema, que es algo bueno recordar.

Es evidente que a veces es un poco molesto, y si no es en la cultura de su entorno de trabajo para estar en el clavo en su robsutness puede hacer que parezca bueno uno-dos-zapatos. Pero creo que es una buena idea. Es algo así como el intento de Delphi en el manual de recolección de basura forzada.

Si va a crear el objeto en el constructor de una clase y el objeto será propiedad de la clase envolvente, tendrá que liberar en destructor de la clase propietaria.

Yo tiendo a usar FreeAndNil () en lugar de llamar gratuito.

EDIT: Pero como han dicho otros, que sin duda siempre quiere liberar lo que se crea

.

Sí, es siempre una buena idea (esencial) si el código que crea el objeto es responsable de free'ing ella. Si no, entonces try / finally no es apropiado pero por otra parte tampoco es .Free en cualquier caso!

Sin embargo, puede ser engorroso tener este código repetitivo salpicando su "lógica de negocio", y es posible que desee considerar un enfoque que tiene la misma garantía de liberar a sus objetos, sino que es mucho más limpio (y tiene otros beneficios), como el mío AutoFree () aplicación.

Con AutoFree () el código podría entonces ser escrito:

aObject := TObject.Create;
AutoFree(@aObject);

aObject.AProcedure();

o, como alternativa, ya que la aplicación utiliza una referencia a una referencia (para permitir la auto-NIL'ing, así como Free'ing), incluso se puede pre-registrar sus referencias que desea ser AutoFree'd mantener dicha declaraciones de limpieza lejos de su lógica de negocio y mantener la verdadera "carne" de su código tan limpio como sea posible (esto es especialmente beneficioso cuando potencialmente varios objetos tienen que ser Free'd):

AutoFree(@aObject1);
AutoFree(@aObject2);

aObject1 := TObject.Create;
aObject1.AProcedure();

// Later on aObject2 is (or may be) also created
 :

No se muestra en mi publicación original es una adición posterior al mecanismo para apoyar el registro de varias referencias en una sola AutoFree () llamada, pero estoy seguro de que pueda averiguar los cambios necesarios para apoyar esto por su cuenta, si deseamos ser capaces de hacer esto:

AutoFree([@aObject1, @aObject2]);

aObject1 := TObject.Create;
aObject1.AProcedure();

// Later on aObject2 is (or may be) also created
 :

Incluso si es muy recomendable para hacer eso, no siempre lo hacen.

Mis reglas de usar o no usar el try / finally:

  • La posibilidad de que el objeto a estrellarse y arder.
  • de veces que se crea
  • Número del objeto. Si sé que el objeto se crea raramente (no más de 5-6 en el tiempo el tiempo de vida de aplicaciones) que puedo vivir con una pérdida de memoria de 20 KB - en caso de que 'muere' si no son liberados.
  • La cantidad de memoria perdida en caso de que el objeto se bloquea.
  • complejidad
  • Código. Try / excepto está haciendo el código para ver realmente feo. Si existe un procedimiento de 5 líneas, siempre uso try / except.
  • división del archivo de la aplicación. Si sus necesidades de aplicaciones que se ejecuten durante días, entonces yo definitivamente quiero liberar cualquier pedazo de la memoria otra cosa que la fuga se acumulará.

El único lugar donde es difícil tomar una decisión es cuando se necesita el rendimiento, mientras que la creación de los objetos miles de veces (en un bucle, por ejemplo). En este caso, yo no uso try / except si el objeto está llevando a cabo tareas simples y hay una pequeña oportunidad de verlo estrellarse.

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top