C# 为什么WinForms设计器会生成一些';不便';代码在其dispose方法中?

C# 为什么WinForms设计器会生成一些';不便';代码在其dispose方法中?,c#,winforms,visual-studio,C#,Winforms,Visual Studio,创建表单或用户控件时,WinForms设计器将生成一个如下所示的dispose方法: protected override void Dispose(bool disposing) { if (disposing && (components != null)) { components.Dispose(); } base.Dispose(disposing); }

创建表单或用户控件时,WinForms设计器将生成一个如下所示的dispose方法:

    protected override void Dispose(bool disposing)
    {
        if (disposing && (components != null))
        {
            components.Dispose();
        }
        base.Dispose(disposing);
    }
    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);
    }
此代码的问题在于,如果对其进行编辑以处理其他对象,可能会导致错误行为。我见过.designer.cs文件中的dispose方法如下所示:

    protected override void Dispose(bool disposing)
    {
        if (disposing && (components != null))
        {
            components.Dispose();
        }
        base.Dispose(disposing);
    }
    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);
    }
。。。这是不正确的,因为处置_myDisposable和_myOtherDisposable不应取决于组件是否为空

因此,忽略关于编辑此设计器生成的代码是否是良好实践的争论,忽略您可以通过编辑模板来更改它的事实,我的问题是:为什么设计器不生成看起来更像这样的代码

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

此代码具有相同的最终结果,但更安全,在修改过程中更不容易出错。

您基本上是对的,您甚至没有提到它被放在Designer.cs文件中这一事实

您必须首先将其移动(到MyForm.cs),然后对其进行编辑。有点常识

但这在很大程度上是学术性的,components==null只在完全空的表单上才是真的。放下一个按钮或标签,问题就不会出现了


我刚刚检查过,即使是在空表单上,它也不是
null
。(好的,就FX4+而言)

答案是:因为您的便利性并不是在Microsoft编写此函数的人最关心的问题。或者他们认为,作为一名非Microsoft员工,您不可能成为一名优秀的程序员,因此,您可能应该远离风险业务,例如修改对象的Dispose()方法


顺便说一句,Dispose()方法位于.Designer.cs文件中指定为“请勿编辑此设计器生成的代码”的区域之外,因此我认为可以对其进行编辑。

处理表单上包含资源的处置的推荐方法是使用FormClosing或FormClosed事件。UserControl也有一个用于相同目的的已处理事件。

我认为这是因为Microsoft的“官方”
IDisposable
模式试图适应太多不必要的情况

有关更多详细信息,请参阅斯蒂芬·克利里(Stephen Cleary)的这篇优秀文章:[你母亲从未告诉过你关于IDisposable的事]。他对
IDisposable
的问题以及如何解决这些问题有着深刻的见解

Stephen提供了一条简单的指导原则:不要在单个类中混合托管和非托管资源;相反,将每个非托管资源包装在一个
IDisposable
类中,该类的唯一目的是处置非托管资源


如果一个人遵循这一指导原则,那么这种神秘的
Dispose
方法就不再是必要的,同时也会用微软推荐的模式解决一大堆其他更严重的问题。

第一个和第三个代码块(几乎)是相同的。还是我遗漏了什么?@Erno-你是对的,因为
&&
会短路。所以毫无疑问(spoon)?只有当disposing为true且components不为null时,才会输入第一个代码块中的if语句,这意味着如果components为null,则不会执行放入其中的任何其他内容。只要disposing为true,就会在第三个块中输入if语句,这样就可以安全地在其中添加额外的内容。但是,如果您想通过将其放入if()语句中来处理其他内容,它们的行为将有所不同。组件在VS 2010中似乎永远不会为null,但在VS 2008及以下版本中,它将始终为null,除非您在表单中专门添加一个组件(如计时器)。关闭和关闭都是过时的,替换为.NET 2.0中的FormClosing和FormClosing。“你在哪里找到这条建议的?”汉斯,我已经相应地编辑了回复;几年前,我被口头告知使用Closing/Closed,但我忘记了它们实际上被命名为FormClosing和FormClosed。我并没有意识到有其他名称的过时事件。+1。即使如此,在IDisposable中包装它们之后,在处理完它们后仍然需要调用
Dispose()
,无论是显式调用还是通过
using(){}
。否则,这种行为并不比根本没有包装好多少。