【问题标题】:Event Handlers automatically created by WinForms Designer由 WinForms Designer 自动创建的事件处理程序
【发布时间】:2010-06-18 14:13:01
【问题描述】:

我刚从 VB.NET 迁移到 C#。在 VB 中,要将事件处理程序连接到 Sub,我们使用 Handles 子句。

从表面上看,这在 C# 中不存在。

在使用按钮创建一个简单的应用程序后,我意识到 Window Forms Designer 使用以下代码在 Form1.Designer.cs 中自动为我的 button1_Click 函数创建了一个 EventHandler(在我双击它之后):

this.button1.Click += new System.EventHandler(this.button1_Click);

但在 VB 中,WinForms 设计器会在我的类中的函数头中创建 Handles 子句。

因此,C# 在设计器文件中创建默认的 EventHandler,而 VB 在控件所在的主类中创建。

这是正确的吗?我在这里遗漏了什么吗?

【问题讨论】:

    标签: c# vb.net event-handling


    【解决方案1】:

    您说得对,C# 中没有类似于 VB.NET 的 handles 子句(或相应的 WithEvents 变量装饰器)。这些仅作为经典 VB 的保留存在于 VB.NET 中,并且它们在使用中有开销(生成的 IL 实际上必须监视设置变量的所有位置,以便分离和附加 handles 该事件的所有函数)。

    如果您检查 VB.NET 窗体或控件的 IL,您实际上会发现为每个 WithEvents 变量创建了一个属性,并且 setter 负责删除所有来自旧值的实际处理程序(假设它非空)并将它们附加到新值(假设它非空)。

    在 VB.NET 中 C# 事件处理的类比是 AddHandler 语句。

    【讨论】:

    • @RHaguiuda:最简单的方法是在 Reflector 中打开你的程序集并检查它。在 C# 中查看它会让您更好地了解幕后实际发生的事情。
    • 有一个与Handles 相关的开销,是的,但大多数时候它肯定是微不足道的吗?
    • @MarkJ:从性能的角度来看,很可能,是的,但是在您的类中为 WithEvents 的每个单个变量都有一个属性(这意味着两个函数) (例如,表单上的所有控件)可能会产生很多不必要的膨胀。
    • @Adam 但它有什么实际区别吗?它会显着减慢代码速度或增加内存占用,还是会妨碍开发人员?
    • @MarkJ:它很可能会碍事;虽然在使用表单显式处理(并超出范围)的实例上有WithEvents,但没有什么要求是这种情况。附加的事件处理程序可以(更确切地说,)导致对象不被收集这一事实变得更加成问题。 WithEvents 修饰符甚至更少表明您可能需要担心它;如果你有一个WithEvents 变量,那么一旦你的对象不再需要,你必须将它设置为null,否则直到目标是它才会被收集。
    【解决方案2】:

    VB Handles 关键字只是语法糖,基本上可以执行您在 C# 中看到的相同操作。你可以用同样的方式写 VB,但你为什么会呢?

    C# 方法(您可以在 VB 中模拟)确实提供了更大的灵活性(即为两个不同的控件调用相同的方法)。

    【讨论】:

    • handles 关键字与 WithEvents 关键字密切相关,在 C# 中没有等效项。
    【解决方案3】:

    这种行为是绝对正确的,你没有遗漏任何东西。

    在 VB 中,您可以使用 Handles 关键字或 AddHandlerAddressOf 运算符订阅事件。 Visual Studio 对设计器生成的事件使用 Handles 关键字。由于事件处理程序必须在代码隐藏文件中而不是设计器文件中,因此您可以在编辑代码隐藏文件时看到它们。如果 Visual Studio 使用AddHandler,它会将该代码插入到设计器代码文件中的InitializeComponent 方法中。

    另一方面,C# 有一个运算符 (+=) 仅用于订阅事件。因此,该代码进入设计器文件,而不是在代码隐藏文件中,以避免将设计器生成的代码与用户代码混合。

    希望这会有所帮助!

    【讨论】:

      【解决方案4】:

      是的,这是正确的,设计师在生成的 *.designer.cs 文件中创建它。您当然可以使用相同的语法手动创建事件处理程序。这种行为是通过部分类功能实现的,您可以在不同的文件中定义类的各个部分。

      【讨论】:

        【解决方案5】:

        += 视为AddHandlerAddressOf

        【讨论】:

          【解决方案6】:

          在 Form1.cs[Design] 中修改的所有内容都将在 Form1.Deisgner.cs 中包含代码部分 这就是 C#.NET 知道如何让内容出现的方式。

          它还应该在您的 Form1.cs 中创建一些代码,您可以在其中实际填写事件中的内容。

          【讨论】:

            猜你喜欢
            • 2010-09-25
            • 1970-01-01
            • 2013-08-15
            • 1970-01-01
            • 2013-12-24
            • 1970-01-01
            • 2022-01-23
            • 2019-04-13
            • 2019-09-28
            相关资源
            最近更新 更多