2012-01-09 4 views
5

Cuando se crea un formulario o un control de usuario, el diseñador de Windows Forms genera un método dispose que tiene este aspecto:¿Por qué el diseñador de WinForms genera un código un tanto "inconveniente" en su método de eliminación?

protected override void Dispose(bool disposing) 
    { 
     if (disposing && (components != null)) 
     { 
      components.Dispose(); 
     } 
     base.Dispose(disposing); 
    } 

El problema con este código es que puede conducir a un comportamiento incorrecto si se edita nunca deseche objetos adicionales. He visto .designer.cs archivos con los métodos Desechar que se ven así:

protected override void Dispose(bool disposing) 
    { 
     if (disposing && (components != null)) 
     { 
      components.Dispose(); 
      if (_myDisposable != null) 
       _myDisposable.Dispose(); 
      if (_myOtherDisposable != null) 
       _myOtherDisposable.Dispose(); 
     } 
     base.Dispose(disposing); 
    } 

... lo cual es incorrecto, ya que la disposición de _myDisposable y _myOtherDisposable no debe depender de si o no componentes es nula.

Así que, ignorando el argumento sobre si es una buena práctica editar este código generado por el diseñador e ignorando el hecho de que puede cambiarlo editando las plantillas, mi pregunta es: ¿Por qué el diseñador no genera código? que se parece más a esto?

protected override void Dispose(bool disposing) 
    { 
     if (disposing) 
     { 
      if(components != null) 
       components.Dispose(); 
     } 
     base.Dispose(disposing); 
    } 

Este código tiene el mismo resultado final, pero es más seguro y menos propenso a errores durante la modificación.

+0

El primer y tercer bloque de códigos son (casi) lo mismo. ¿O me estoy perdiendo algo? –

+0

@Erno - Tiene razón, ya que '&&' provocará un cortocircuito. – Oded

+0

Entonces, no hay pregunta (cuchara)? –

Respuesta

4

La respuesta es: porque su conveniencia no era la principal preocupación de quien escribió esta función en Microsoft. O tal vez pensaban que usted, al ser un empleado que no es de Microsoft, no puede ser nada bueno como programador, por lo tanto, probablemente debería mantenerse alejado de negocios riesgosos como la modificación del método Dispose() de un objeto.

Por cierto, el método Dispose() se encuentra fuera del área dentro del archivo .Designer.cs que se designa como "no edite este código generado por el diseñador", por lo que supongo que está bien editarlo.

1

Tienes razón en su mayoría, y ni siquiera mencionaste el hecho de que se coloca dentro del archivo Designer.cs.

Primero tendrá que moverlo (a MyForm.cs) y luego editarlo. Con un poco de sentido común ...

Pero es en gran medida académico, componentes == null solo será cierto en un formulario completamente vacío. Soltar 1 botón o etiqueta y el problema no aparece.

Acabo de comprobar, incluso en un formulario vacío no es null. (OK, solo para Fx 4+ aparentemente)

+0

Los componentes nunca parecen ser nulos en VS 2010, pero en VS 2008 y versiones inferiores siempre serán nulos a menos que agregue específicamente un componente como un temporizador a su formulario. –

1

La forma recomendada de manejar la eliminación de recursos contenidos en un formulario es utilizar los eventos FormClosing o FormClosed. UserControl tiene un evento Disposed para el mismo propósito.

+0

Cerrado y Cerrado son ambos obsoletos, reemplazados por FormClosing y FormClosed en .NET 2.0. ¿Dónde encontraste esa recomendación? –

+0

@Hans, he editado la respuesta en consecuencia; Me dijeron verbalmente unos años atrás que utilizara Closing/Closed y olvidé que en realidad se llamaban FormClosing y FormClosed. En realidad no sabía que había eventos obsoletos con los otros nombres. –

3

Yo diría que esto se debe a que el patrón IDisposable "oficial" de Microsoft intenta acomodar demasiadas situaciones, innecesariamente. Para obtener más información, consulte este excelente artículo de Stephen Cleary: What your mother never told you about IDisposable. Él tiene algunas grandes ideas sobre los problemas con IDisposable, y cómo solucionarlos.

Stephen ofrece una directiva simple: simplemente no mezcle recursos administrados y no administrados en una sola clase; en su lugar, envuelva todos los recursos no administrados en una clase IDisposable cuyo único propósito es deshacerse del recurso no administrado.

Si uno sigue esta pauta, tales métodos arcanos Dispose dejan de ser necesarios, al mismo tiempo que resuelven un montón de otros problemas más serios con el patrón recomendado por Microsoft.

+0

+1. Aun así, después de envolverlos en IDisposable, es necesario invocar 'Dispose()' cuando hayas terminado con ellos, ya sea explícitamente o mediante 'using() {}'. De lo contrario, el comportamiento no es mucho mejor que no haberlos envuelto en absoluto. – JMD

Cuestiones relacionadas