Interlocked.Exchange<T>
的文档包含以下备注:
此方法重载优于
Exchange(Object, Object)
方法重载,因为后者需要对目标对象的后期绑定访问。
我对这张纸条感到非常困惑。对我来说,"后期绑定"是指运行时方法调度,似乎与原子交换两个内存位置的技术细节没有任何关系。纸条在说什么?在这种情况下,"后期绑定访问"是什么意思?
canton7 的回答是正确的,感谢您的呼喊。我想补充几点。
这句话,就像 .NET 文档中经常出现的情况一样,既选择构造奇怪的单词用法,又完全没有抓住重点。对我来说,突出的糟糕的单词选择不是"迟到",这只是没有抓住重点。真正可怕的单词选择是使用"目标对象"来表示变量。 变量不是对象,就像你的袜子抽屉是一双袜子一样。变量包含对对象的引用,就像袜子抽屉包含袜子一样,这两件事不应该混淆。
如您所注意的,首选T
版本的原因与后期绑定无关。首选T
版本的原因是C# 不允许对ref
参数进行变量转换。 如果你有一个类型为Turtle
的变量shelly
,你不能ref shelly
传递给一个需要ref object
的方法,因为该方法可以将Tiger
写入ref object
。
那么使用Object
对shelly
进行过载的逻辑后果是什么?只有两种可能性:
- 我们将
shelly
的值复制到Object
类型的第二个变量,进行交换,然后将新值复制回来,现在我们的操作不再是原子的,这就是调用联锁交换的全部意义。 - 我们将
shelly
更改为Object
型,现在我们处于一个非静态类型,因此容易出错的世界,我们永远无法确定shelly
仍然包含对Turtle
的引用。
由于这两种替代方法都很糟糕,因此应使用泛型版本,因为它允许别名变量在整个操作过程中具有正确的类型。
Interlocked.Exchange(object, object)
的等效备注是:
从 .NET Framework 2.0 开始,
Exchange<T>(T, T)
方法重载为引用类型提供了一种类型安全的替代方法。建议调用它而不是此重载。
虽然我以前没有听说过它以这种方式使用,但我认为"后期绑定"只是意味着"非类型安全",因为您需要在使用之前将object
转换为具体类型(在运行时(。
除了虚拟方法调度之外,"后期绑定"通常也指反射,因为要类似调用的确切方法直到运行时才知道。
引用Eric Lippert的话:
基本上,"早期绑定"是指"绑定分析由编译器执行并烘焙到生成的程序中";如果绑定失败,则程序不会运行,因为编译器没有进入代码生成阶段。"后期绑定"是指"绑定的某些方面将由运行时执行",因此绑定失败将表现为运行时失败
(强调我的(。在这个相当宽松的定义下,将object
转换为具体类型,然后对其调用方法可以被视为"后期绑定",因为绑定的一个元素在运行时执行,并且可能在运行时失败。