11

Recientemente he notado cierto comportamiento con el Visual Studio Designer (C#) que no entiendo y me preguntaba si alguien podría aclarar ...¿Por qué el IDE de Visual Studio a veces inicializa el objeto "this.components: y otras veces no?

Un algunas de mis formas de Windows, la primera línea del diseñador genera código lee;

this.components = new System.ComponentModel.Container(); 

Cuando este es el caso, el método dispose, en ese mismo archivo del diseñador, dispose método coloca dos llamadas "Eliminar" dentro de la condición "si" de la siguiente manera;

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

es decir, no se llama a nada a menos que la eliminación sea verdadera, Y los componentes no son nulos.

En algunas otras formas, falta esa primera línea en el código generado por el diseñador. En estos casos la llamada base.Dispose se encuentra fuera de la condición "si" como tal ...

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

he dado cuenta de esto, mientras que la pista de un error con una forma no cerrando, donde this.components era nula, sin embargo, la llamada base.Dispose estaba dentro de esa condición (sospecho que el código del diseñador había sido manipulado, pero esa es otra historia.

Qué controla este comportamiento?

(Algunas formas anteriores en el proyecto fueron creados en 2005 y VS ahora usamos VS 2008 - ¿pista?)

Respuesta

4

Esto es un comportamiento reproducible. Cuando crea un formulario nuevo, comienza con un esqueleto que incluye la llamada al constructor this.components. Cuando luego agrega un componente (digamos un temporizador) y lo elimina de nuevo, el diseñador regenera el código, ahora sin la llamada del constructor. Eso no es un error.

Fwiw, el esqueleto de código es generado por Common7\IDE\ItemTemplates\CSharp\Windows Forms\1033\Form.zip\form.designer.cs

Al ver la llamada base.Dispose() dentro de la instrucción if() es un error. Eso podría ser autoinducido. O podría ser una versión beta del código del esqueleto. VS2005 lo hace bien. Verifique la carpeta ItemsTemplatesCache.

+0

Gracias nobugz. He tenido la oportunidad de probar este escenario en VS2005 ahora también. Está bien. Solo puedo suponer que, como dices, esto fue "autoinducido". –

+0

"ahora sin la llamada del constructor". Entonces, ¿qué punto en '(components! = Null)' comprueba si no hay inicialización de 'components' en ningún lado? ¿Quién, cuándo y dónde inicializa 'componentes'? Por cierto, vino aquí desde VS2010, .NET4.0 – Fulproof

+0

Parece que tiene una nueva pregunta. Puede formularla haciendo clic en el botón Preguntar. –

1

¡Error interesante! De hecho, parece un error en una versión del diseñador/plantilla. Por supuesto, si cree que el código del diseñador había sido manipulado, todas las apuestas son bastante-mucho de todos modos ...

Sin embargo, en VS2008, que genera la versión indudablemente correcta:

if (disposing && (components != null)) 
{ 
    components.Dispose(); 
} 
base.Dispose(disposing); 

Así que la base Dispose(...) se llama. No tengo el VS2005 a mano para probarlo, desafortunadamente. Sin embargo - no inicializar los componentes hasta que se tiene que - la declaración es:

private System.ComponentModel.IContainer components = null; 

Y luego si es necesario, que se rellena en InitializeComponent:

private void InitializeComponent() 
{ 
    this.components = new System.ComponentModel.Container(); 
    //... 
} 

supongo que con esta construcción solo tiene que mantener InitializeComponent (y no los campos en sí).

+0

Yo tampoco Marc. Tendré que intentarlo en casa esta noche. Gracias. –

+0

"si crees que el código del diseñador ha sido manipulado", ¡soy yo porque no entiendo cómo atenuarlo! – Fulproof

0

He visto esto suceder, y de vez en cuando recibo advertencias sobre el método Dispose sobre los componentes que nunca tienen su valor asignado, o que no están definidos.

creo que es una combinación de dos cosas:

  1. Ligeramente diferente de generación de código entre versiones de Visual Studio
  2. El método Dispose solamente se genera si no lo es ya en el archivo, mientras que InitializeComponent (y las declaraciones asociadas) se genera cada vez

Esto da como resultado una sección InitializeComponent/declarations que está desfasada con el método Dispose.

+0

"entre versiones de Visual Studio" - vino aquí desde la creación de nuevas aplicaciones de Windows Forms en VS2010, .NET4.0 sin usar ninguna otra versión (aunque UI tiene VS2008 instalado en la PC) – Fulproof

3

6 años después y este problema todavía ocurre. Logré localizar al menos una causa para que ocurra.

Al probar si su componente tiene un constructor que toma un IContainer, System.ComponentModel.Design.Serialization.ComponentCodeDomSerializer almacena en caché una referencia al tipo de IContainer para su proyecto. Si luego guarda un objeto para otro proyecto dentro de la misma solución, o tal vez cuando haya realizado algún otro tipo de cambios en su proyecto, ComponentCodeDomSerializer ya no podrá encontrar el constructor ya que el Tipo de IContainer ya no es igual a su Tipo en caché.

Si esto está sucediendo un montón para su proyecto, hay una solución muy fea. Agregue este VB o C#VisualStudioWorkaroundSerializer clase a su solución. A continuación, agregue el atributo DesignerSerializer(GetType(VisualStudioWorkaroundSerializer), GetType(CodeDomSerializer)) a su componente. Cada vez que se guarde su componente, este serializador personalizado detectará el problema, lo reparará y lo obligará a guardar nuevamente cada vez que este problema esté a punto de ocurrir.

Cuestiones relacionadas