我的一位同事声称在.net中,委托始终被固定在堆上。我似乎找不到任何权威的信息来证明这个说法是否正确。请问这是真的吗?
请注意,固定对象不是免费的。它实际上会给垃圾回收器带来相当大的负担。小量使用是可以的,但让每个.Net委托都被固定可能会对性能产生非常明显的影响。
委托本身没有被固定,可以由GC移动。但这并不一定意味着您需要将其固定。
在JIT时间,生成的非托管代码以及如果使用非托管函数指针调用委托代码时实际使用的代码将不会被移动。CLR团队的Chris Brumme在他的博客中详细解释了这一点(关键句子是:该存根存在于GC堆之外的固定内存中。):
同样的道理,托管委托可以转换为非托管代码,并作为非托管函数指针暴露。对这些指针的调用将执行从非托管到托管的转换;调用约定的更改;进入正确的AppDomain;以及任何必要的参数转换。显然,非托管函数指针必须引用固定地址。如果GC正在重定位它,那将是一场灾难!这导致许多应用程序为委托创建一个固定句柄。这是完全不必要的。实际上,非托管函数指针引用一个本地代码存根,我们动态生成该存根以执行转换和转换。该存根存在于GC堆之外的固定内存中。所以你的同事在技术上并不正确——委托可以被移动,而不是固定的。但是,从精神上讲,同事是“正确”的——如果你使用非托管函数指针调用委托,你不一定需要固定委托,但你需要保证委托的生命周期。