Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why does the Visual Studio IDE sometimes initialize the "this.components object: and other times not?

I've recently noticed some behaviour with the Visual Studio Designer (C#) that I don't understand and was wondering if someone could clarify...

One some of my Windows Forms, the first line of the designer generated code reads;

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

When this is the case, the dispose method, in that same designer file, the dispose method places two "Dispose" calls within the case "if" condition as follows;

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

i.e. Nothing is called unless disposing is true, AND components is not null.

On some other forms, that first line in the designer generated code is missing. In these cases the base.Dispose call is outside the "if" condition as such...

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

I have noticed this while tracking down a bug with a form not closing, where this.components was null, yet the base.Dispose call was inside that condition (I suspect the designer code had been tampered with but that's another story.

What controls this behaviour?

(Some earlier forms in the project were created in VS 2005 and we now use VS 2008 - clue?)

like image 582
Stuart Helwig Avatar asked Feb 17 '09 04:02

Stuart Helwig


2 Answers

This is reproducible behavior. When you create a new form, it starts out with a skeleton that includes the this.components constructor call. When you then add a component (say a Timer) and remove it again, the designer regenerates the code, now without the constructor call. That isn't a bug.

Fwiw, the skeleton code is generated by Common7\IDE\ItemTemplates\CSharp\Windows Forms\1033\Form.zip\form.designer.cs

Seeing the base.Dispose() call inside the if() statement is a bug. That might be self-induced. Or it might be a beta version of the skeleton code. VS2005 does it right. Do check the ItemsTemplatesCache folder.

like image 125
Hans Passant Avatar answered Sep 28 '22 02:09

Hans Passant


6 years later and this problem still occurs. I've managed to track down at least one cause for it happening.

When testing if your component has a constructor that takes an IContainer, System.ComponentModel.Design.Serialization.ComponentCodeDomSerializer caches a reference to the Type of IContainer for your project. If you then save an object for another project within the same solution, or perhaps when you have made some other types of changes in your project, ComponentCodeDomSerializer can no longer find the constructor as the Type of IContainer is no longer equal to it's cached Type.

If this is happening lots for your project, there is a very ugly workaround. Add this VB or C# VisualStudioWorkaroundSerializer class to your solution. Then add the attribute DesignerSerializer(GetType(VisualStudioWorkaroundSerializer), GetType(CodeDomSerializer)) to your component. Whenever your component is saved, this custom serializer will detect the problem, fix it, and force you to save again whenever this issue is about to occur.

like image 33
Jeremy Lakeman Avatar answered Sep 28 '22 04:09

Jeremy Lakeman