Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/310.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 在处理方法中删除委托成员时,是否可以使用equals赋值?_C#_Delegates_Operators_Variable Assignment_Dispose - Fatal编程技术网

C# 在处理方法中删除委托成员时,是否可以使用equals赋值?

C# 在处理方法中删除委托成员时,是否可以使用equals赋值?,c#,delegates,operators,variable-assignment,dispose,C#,Delegates,Operators,Variable Assignment,Dispose,我的课堂上有以下代码 public class Receiver : IReceiver { public event EventHandler Received; public void Dispose() { Dispose(true); GC.SuppressFinalize(this); } protected virtual void Dispose(bool disposing) {

我的课堂上有以下代码

public class Receiver : IReceiver
{

    public event EventHandler Received;

    public void Dispose()
    {
        Dispose(true);
        GC.SuppressFinalize(this);
    }

    protected virtual void Dispose(bool disposing)
    {
        if (disposing)
        {
            if (Received != null)
            {
                foreach (EventHandler delegateMember in Received.GetInvocationList())
                {
                    Received -= delegateMember;
                }
            }
        }
    }
}
这段代码的工作原理是,当我处理我的类时,连接到接收到的事件的任何事件都将被单独删除

我一直在想,与其说它太冗长,不如说下面的简洁版本是否也会有同样的效果

    protected virtual void Dispose(bool disposing)
    {
        if (disposing)
        {
            Received = null;
        }
    }
基本上,这取决于Microsoft在实现委托重载时如何创建运算符重载。我知道所有的文档都说使用+=订阅活动,使用-=取消订阅活动。我还看到文档中说,当最后一个订户被删除时,事件将被分配为null。文档没有说明的是,将事件分配为null是否会产生取消订阅所有事件的效果

我想知道这是否可行,是否有任何文档表明可能的简洁代码是正确的行为

更新:


我对c#编译器做了更多的挖掘,发现null赋值只在定义事件的类中有效。+=和-=始终可从类内部和外部使用。这导致我认为使用=null版本是可以接受的。但是,这只是猜测,我还没有看到任何文档明确说明这是受支持的功能。

没有理由不在此处将
null
分配给代理

如果您不在定义该事件的类的范围内,则不能只分配
null
。对于任何使用该类的人来说,他们应该只关心他们自己的处理程序,他们可以添加或删除这些处理程序。他们无法访问其他人的处理程序

您需要记住代理是不可变的。对事件使用
+=
不会改变委托以向该委托添加新方法,它会创建一个新委托,当调用该委托时,将调用两个已添加到一起的委托。使用
-=
创建一个委托,该委托调用除第二个操作数之外的第一个操作数的所有调用。因此,反复调用
-=
会不断创建越来越多的委托,每个委托调用的内容越来越少,直到最终您到达委托不再调用任何东西的地步。只分配
null
相当于只创建一个不做任何事情的委托,然后直接分配它


因此,当您反复调用
-=
时,在开始之前分配给事件的原始代理仍然存在,以及N个中间代理。也就是说,没有一个委托可能被任何根元素引用,因此它们都有资格被收集。如果您只分配
null
您仍然有原来存在的同一个孤立委托,您就不再有任何中间委托。

@DStanley委托仍将引用这些对象,是的,但委托本身将不再是根委托,或从根委托访问,这样就不会让那些被引用的对象保持活动状态了。在发布问题之前,我确实检查了一下是否安静。最基本的问题是使用=和使用-=。在MSDN中,我能找到的最接近的是在本页底部,它说当取消订阅事件处理程序的最后一个实例时,将分配null。我了解您在这里发布的所有内容,并且我知道代码将以两种方式编译。我想问题的关键部分是。。。是不是-=也在做其他事情,但是=作业没有做?如果是,你怎么能确定?到目前为止,我发现的唯一一个与此接近的引用是在本页的底部,它明确表示要使用-=运算符。它确实说您可以测试null以查看是否有订阅者。它并没有说您可以使用=运算符。@ColinDawson除了创建一个新的委托,将第二个操作数从调用列表中排除,然后将该新委托分配给第一个操作数之外,
-=/code>运算符没有做任何事情。因此,创建一个不执行任何操作的新委托(也称为null)并直接分配它是等效的。当然,除非任何一个事件处理程序引用定义事件的对象(并且将超过此接收器),否则没有理由这样做,因为整个接收器应该很快停止在第一个位置扎根,也没有理由将其置空。我理解,问题不是你能不能用代码编写它,但是是否有任何文档支持使用=null?我希望能够简单地使用简洁的代码,因为它看起来非常清晰,但我希望确保在引擎盖下,一切都按照预期工作-与示例中的详细代码相同。我要找的是引证,它说这是一个允许的构造。我不想假设它是有效的。你说的很有道理,我理解你是怎么理解的。@ColinDawson:你似乎有一种误解,认为事件或代表是特殊的——它们不是。事件的支持字段具有委托类型,只要它指向委托对象,该委托的调用列表就会保存对对象的引用,并防止对象被收集。当backbacking字段设置为
null
时,它将无法使委托对象或任何下游对象保持活动状态(尽管它们可以从根对象图的其他部分继续访问)@ColinDawson:您是指语言规范中的这句话?在声明事件成员的类中,事件的行为类似于委托类型的字段(前提是该事件不是抽象的且不声明访问器)。该字段存储对代表事件的委托的引用