我正在读一本关于 C# 和 CLR 的书,但有一点无法理解。正文如下:
To fix this race condition, many developers write the OnNewMail method as follows:
// Version 2
protected virtual void OnNewMail(NewMailEventArgs e) {
EventHandler<NewMailEventArgs> temp = NewMail;
if (temp != null) temp(this, e);
}
The thinking here is that a reference to NewMail is copied into a temporary variable, temp, which refers to the chain of delegates at the moment the assignment is performed. Now, this method compares temp and null and invokes temp, so it doesn’t matter if another thread changes NewMail after the assignment to temp. Remember that delegates are immutable and this is why this technique works in theory.
所以,问题是:为什么它会起作用?我认为 temp 和 NewMail 对象引用同一个对象,无论必须更改哪个对象 - 结果都会影响两者。谢谢!
最佳答案
CLR 和 MulticastDelegate
中的委托(delegate)类型特别是 type,尽管它们是引用类型,但属于称为“不可变”类型的罕见类型组。这意味着此类类型的引用分配操作会创建实例的副本,这与仅复制引用值的常规引用类型的分配不同。所以当你写:
EventHandler<NewMailEventArgs> temp = NewMail;
NewMail
引用的委托(delegate)的新副本创建并将对此副本的引用分配给 temp
变量,因此执行此行后将有 EventHandler<NewMailEventArgs>
的两个实例delegate: NewMail
引用的实例以及 temp
引用的另一个实例(不是像您想象的那样由两个变量引用的单个实例)。这就是为什么现在您可以安全地调用 temp
指向的委托(delegate)。因为在调用委托(delegate)的一段时间内它不能被另一个线程置空。
关于c# - 如果我将对事件对象的引用复制到另一个对象并随后更改事件对象会怎样?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/55322255/