Csharp/C#教程:复制代表分享


复制代表

我刚刚在MSDN上阅读有关事件的页面,我遇到了一段令我困惑的示例代码。

有问题的代码是这样的:

// Make a temporary copy of the event to avoid possibility of // a race condition if the last subscriber unsubscribes // immediately after the null check and before the event is raised. EventHandler handler = RaiseCustomEvent; 

我理解代码的意图,但我没有看到该特定行如何制作任何东西的副本。 它所做的只是复制参考 ; 它实际上并没有制作委托实例的深层副本。 所以为此,它实际上并没有完全阻止竞争条件。

我错过了一些明显的东西吗?

代理是不可变的,因此保证代码中获得的引用不会改变。 如果用户在空检查后订阅或取消订阅,则将创建新的委托并将其设置为该事件。 但是,由于您具有对完全不同的对象的引用并调用它,因此您不必担心它为null。

你是对的; 它正在复制参考。

但是,代表是不可改变的; 当您向事件添加处理程序时,会创建一个新委托,将当前处理程序与新处理程序组合在一起,然后分配给该字段。

字段引用的Delegate实例不能更改,因此它可以避免竞争条件。

Eric Lippert已在一篇非常详细的文章中介绍了这一点。

这也来自MSDN ..

“委托的调用列表是一组有序的委托,其中列表的每个元素都只调用委托所代表的方法之一。调用列表可以包含重复的方法。在调用期间,方法按顺序调用它们出现在调用列表中。委托会尝试调用其调用列表中的每个方法; 重复项每次出现在调用列表中时都会被调用一次。 委托是不可变的;一旦创建,委托的调用列表就不会改变。

if (whatever != null) whatever(); 看起来它确保在调用whatever()时它们永远不会为null,但它实际上并不确保在线程场景中。 不同的线程可以在检查和调用之间设置whatever = null

 Foo temp = whatever; if (temp != null) temp(); 

此代码消除了空取消引用的可能性,因为temp是本地的,因此永远不会被其他线程修改。 所以它确实可以防止竞争。 但它并没有阻止所有相关的竞争条件。 Eric Lippert对代码中的其他一些问题进行了更详尽的讨论。

上述就是C#学习教程:复制代表分享的全部内容,如果对大家有所用处且需要了解更多关于C#学习教程,希望大家多多关注—计算机技术网(www.ctvol.com)

本文来自网络收集,不代表计算机技术网立场,如涉及侵权请点击右边联系管理员删除。

如若转载,请注明出处:https://www.ctvol.com/cdevelopment/953074.html

(0)
上一篇 2021年11月19日
下一篇 2021年11月19日

精彩推荐