我最近注意到一些我不理解的Visual Studio Designer(C#)的行为,并且想知道是否有人可以澄清......
我的一些Windows窗体,设计器的第一行生成代码读取;
this.components = new System.ComponentModel.Container();
在这种情况下,dispose方法,在同一个设计器文件中,dispose方法在case“if”条件下放置两个“Dispose”调用,如下所示;
protected override void Dispose(bool disposing)
{
if (disposing && (components != null))
{
components.Dispose();
base.Dispose(disposing);
}
}
即。除非disposing为true,否则不会调用任何内容,AND组件不为null。
在其他一些表单中,缺少设计器生成代码中的第一行。在这些情况下,base.Dispose调用超出了“if”条件......
protected override void Dispose(bool disposing)
{
if (disposing && (components != null))
{
components.Dispose();
}
base.Dispose(disposing);
}
我已经注意到这一点,同时跟踪一个没有关闭的表单的bug,其中this.components为null,但base.Dispose调用是在那个条件内(我怀疑设计师代码已被篡改但这是另一个故事。
什么控制了这种行为?
(项目中的一些早期形式是在VS 2005中创建的,我们现在使用VS 2008 - 线索?)
答案 0 :(得分:4)
这是可重复的行为。创建新表单时,它首先使用包含this.components构造函数调用的框架。然后,当您添加一个组件(比如一个Timer)并再次删除它时,设计器会重新生成代码,现在没有构造函数调用。这不是一个错误。
Fwiw,骨架代码由Common7\IDE\ItemTemplates\CSharp\Windows Forms\1033\Form.zip\form.designer.cs
在if()语句中查看base.Dispose()调用是一个错误。这可能是自我诱导的。或者它可能是骨架代码的beta版本。 VS2005做对了。检查ItemsTemplatesCache文件夹。
答案 1 :(得分:3)
6年后,这个问题仍然存在。我设法找到了至少一个原因。
在测试组件是否具有使用IContainer的构造函数时,System.ComponentModel.Design.Serialization.ComponentCodeDomSerializer会缓存对项目的IContainer类型的引用。如果然后在同一解决方案中保存另一个项目的对象,或者当您在项目中进行了其他类型的更改时,ComponentCodeDomSerializer将无法再找到构造函数,因为IContainer的类型不再等于它的缓存类型。
如果您的项目发生了很多,那么有一个非常难看的解决方法。将此VB或C# VisualStudioWorkaroundSerializer
类添加到您的解决方案中。然后将属性DesignerSerializer(GetType(VisualStudioWorkaroundSerializer), GetType(CodeDomSerializer))
添加到您的组件。无论何时保存组件,此自定义序列化程序都会检测到问题并进行修复,并在发生此问题时强制您再次保存。
答案 2 :(得分:1)
有趣的故障!它确实听起来像设计师/模板的一个版本中的错误。当然,如果您认为设计师代码已经被篡改,那么所有赌注都是相当不错的......
但是,在VS2008中,它会产生无可置疑的正确版本:
if (disposing && (components != null))
{
components.Dispose();
}
base.Dispose(disposing);
因此调用了基础Dispose(...)
。不幸的是,我还没有得到VS2005来测试它。但是 - 它不会初始化组件,直到它必须 - 声明是:
private System.ComponentModel.IContainer components = null;
然后如果需要它,它会填充在InitializeComponent
中:
private void InitializeComponent()
{
this.components = new System.ComponentModel.Container();
//...
}
我猜这个构造只需要维护InitializeComponent
(而不是字段本身)。
答案 3 :(得分:0)
我已经看到这种情况发生了,我偶尔也会从Dispose方法中得到有关组件的警告,这些组件要么从未分配过值,要么没有定义。
我认为这是两件事的组合:
这会导致InitializeComponent / declarations部分与Dispose方法不同。