【问题标题】:C# event removal syntaxC# 事件删除语法
【发布时间】:2009-08-27 15:38:26
【问题描述】:

我对在 C# 中删除事件处理程序的语法感到困惑。

Something += new MyHandler(HandleSomething); // add
Something -= new MyHandler(HandleSomething); // remove

“new”在每一行创建一个新对象,所以你添加一个对象 然后让它移除一个不同的对象。

这到底是怎么回事?
从语法上肯定看不出来。

【问题讨论】:

标签: c# events handler


【解决方案1】:

+= 和 -= 是名为 Add() 和 Remove() 的内置内部方法的语法快捷方式,它们添加或删除指向内部委托链接列表的指针,委托作为私有字段拥有.当您运行 Remove 时,它​​从链表的头部开始,并一次检查列表中的每个委托,直到找到与您传递给 Remove() 方法的委托“相等”的委托。 (使用 -= 语法)

然后,它从链表中删除那个,并修补链表以保持它的连通性......

在这种情况下,'equals' 方法(对于 delegate())被覆盖,因此它只比较委托的目标和 methodPtr,即使您已经创建了一个新委托传递给 Remove...

【讨论】:

    【解决方案2】:

    “新的 MyHandler”实际上是多余的。你可以简单地做

    Something += HandleSomething; // add
    Something -= HandleSomething; // remove
    

    C# 中的所有事件都是多播委托,因此 += 和 -= 语法表示您正在将一个委托添加/删除到将被调用的委托列表中。

    至于幕后发生的事情,我找到的最好的解释是Jon Skeet's

    【讨论】:

    • 这实际上与提供的示例相同,尽管较新的 C# 为您添加了这一点。
    • 你可以不加新的,但如果你让 Visual Studio 为你填写:“Something +=" 然后 ,自动生成的代码将完成它类似于这个:“某事+=新的MyHandler(HandleSomething);” OP 正在询问引擎盖下发生了什么,以便新的方式起作用。
    • 是的,我最终被叫走了,没有足够的时间来完整回答。两种语法是等效的,编译器推断委托并将新实例添加到多播列表中。即使在删除时,“new EventHandler()”语法仍然有效,因为它查看的是目标和方法签名,而不是特定的对象引用。
    • 虽然这个语法快捷方式和原来的语法快捷方式做同样的事情,但至少这个很有意义。这可以在不引起混淆的情况下使用。我更喜欢这种新语法。
    【解决方案3】:

    您可以将事件视为在引发事件时执行的委托逻辑的占位符方法。单个事件可以有多个订阅者(多播),因此 += 和 -= 语法是附加或删除单个事件处理程序的方式。简单地进行分配会重置事件的订阅,这可能会导致不必要的副作用。

    编辑:this link 详细解释了 C# 中的事件

    【讨论】:

    • 为什么投反对票?这似乎是一个完全有效的回应。
    • 重申 OP 的问题:“为什么我们可以 += 一个新的对象和 -= 一个完全不同的新对象并获得所需的效果?” Josh E 没有回答为什么我们可以附加“a”并删除“b”,其中“a”和“b”是不同的实例,但仍然得到我们想要的。
    • 我曾认为通过谈论订阅我涵盖了这一点。 Charles Bretana 的回答很好地涵盖了这一点,所以我不会编辑我的回复
    猜你喜欢
    • 2011-03-03
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-07-26
    • 2015-04-23
    • 1970-01-01
    • 2019-06-13
    相关资源
    最近更新 更多