C# 处理新表单的正确方法

C# 处理新表单的正确方法,c#,.net,forms,winforms,dispose,C#,.net,Forms,Winforms,Dispose,因此,在我的应用程序中,我倾向于动态创建表单的新实例,然后使用Form.Show()来显示它们(非模态) private void test\u单击(对象发送方,事件参数e) { var form=new myForm(); form.Show(); } 然而,CodeCracker告诉我应该处理这些表单。所以,我用“using”语句包装它们,但它们在打开后立即关闭 使用(var form=new myForm()) { form.Show(); } 我不想使用Form.ShowDialog

因此,在我的应用程序中,我倾向于动态创建表单的新实例,然后使用
Form.Show()
来显示它们(非模态)

private void test\u单击(对象发送方,事件参数e)
{
var form=new myForm();
form.Show();
}
然而,CodeCracker告诉我应该处理这些表单。所以,我用“using”语句包装它们,但它们在打开后立即关闭

使用(var form=new myForm())
{
form.Show();
}

我不想使用
Form.ShowDialog();我不需要它们是模态的

您可以实现某种形式的表单管理器,它将为显示的每个表单订阅,然后它可以处理这些表单。。。比如:

public class FormManager
{
    public T ShowForm<T>()
        where T : Form, new()
    {
        var t = new T();
        t.OnFormClosing += DisposeForm;
        return t;
    }

    void DisposeForm(object sender, FormClosedEventArgs args)
    {
        ((Form)sender).Dispose();
    }
}
公共类表单管理器
{
公共T ShowForm()
其中T:Form,new()
{
var t=新的t();
t、 OnFormClosing+=DisposeForm;
返回t;
}
void DisposeForm(对象发送方,FormClosedEventArgs args)
{
((Form)sender.Dispose();
}
}

您甚至可以在管理器被释放时实现并释放所有未释放的表单:)

因此,根据上面的答案,无论何时关闭非模式表单,都会自动释放它们

我决定通过多次打开我的测试表单并关闭它们来测试这一点。我甚至同时打开了多个实例。一两秒钟后,这些表单使用的内存被回收,这表明它们被正确处理。

嗯,“代码破解器”似乎是该工具的一个非常合适的术语,它的建议肯定会让您编写破坏程序的代码。黄金法则是永远不要相信来自静态代码分析工具的IDisposable建议,它们中没有一个对代码执行有足够的洞察力。他们永远无法确定哪个Dispose()调用可以完成任务

它看不到的是表单类已经知道如何处理自己。这样做很容易,当窗口关闭时,对象变得不可用。当没有更多的窗口时,就没有理由继续使用表单对象。这种奢侈在.NET中并不常见,但肯定是受到45年前为施乐工作的非常聪明的程序员的启发


您只需记住一条特殊规则,即在使用ShowDialog()显示窗口时,它不会自行处理。这是故意的,这使得检索对话框结果风险太大。对ShowDialog()调用使用Using语句非常容易,直到窗口关闭后调用才会返回。

关闭表单后是否需要处理表单?

当您使用
show()
显示表单时,您不需要处理它,因为它将在关闭后处理。但是,当您使用
ShowDialog()
显示表单时,您需要处理表单,因为它在关闭后不会处理

当您关闭
表单时,将向窗口发送一条消息。如果您查看处理
WM_CLOSE
消息的方法的源代码,您将看到:

  • 对于模式表单(您使用
    ShowDialog
    显示),将不会调用
    Dispose
    方法,并且表单在关闭后存在,您可以使用其属性获取一些数据,也可以再次显示它

  • 对于非模态表单(使用
    Show
    显示),在表单关闭后,将调用
    Dispose
    方法

结论如下:

  • 使用
    show
    方法显示表单时,不需要(也不能)调用
    Dispose
    。表单将在关闭后自行处理

  • 使用
    ShowDialog
    显示表单时,需要手动调用
    Dispose
    。一个好的做法是在
    块中使用模态形式

示例

要显示模式对话框,最佳做法是使用
块:

//form will be disposed after the using block
using (var f = new MyForm())
{
    if (f.ShowDialog() == DialogResult.OK)
    {
        //Your logic to handle OK here
    }
}
对于非模态对话框,显示并忽略它:

var f = new MyForm();
f.Show();

答案很清楚。“密码破解者”误导了你。不要使用
使用
。。。。在适当的时候处理表单…我必须同意这里的@L.B-关闭窗口是Dispose()要做的正确事情。根据定义,一个正确实现的Dispose()方法应该使disposed对象处于不可用状态。非模态形式将自动进行GC'd。我在观看任务管理器时进行了测试,内存被回收。我只是检查了实现。Dispose并不总是在内部调用,但它所做的只是从其容器中移除表单并引发disposed事件。所有资源都已经以其他方式释放,垃圾收集不会发生任何事情。(当然,这并不意味着你不应该打电话给dispose,因为这在将来可能会改变。但这意味着你现在不必担心。)@Cameron谢谢你的检查。所以,我想我在想,其他人会怎么做?实际上这表明GC正在回收内存,而不是调用
Dispose
。在这种情况下,
Dispose
不会清理任何本机资源,因此所有内存都由GC管理,并且无论是否调用
Dispose
,它都会被释放。您在所有帐户上都是正确的。我只是讨厌看到《代码破解者》中所有扭曲的行,但同时不想添加抑制规则。我也不想完全摆脱它,因为它为这个初级开发人员提供了大量的见解。只需关闭特定的分析规则,它对您一点帮助都没有。或者学会不太信任工具,这会让你更高级:)谢谢,知道非模态表单自动获取disp是非常有用的