我在another question中询问,出现了一条注释,指示.NET框架的Array.Copy
方法使用非托管代码。我继续研究Reflector,发现Array.Copy
方法重载之一的签名定义如下:
[MethodImpl(MethodImplOptions.InternalCall), ReliabilityContract(Consistency.MayCorruptInstance, Cer.MayFail)]
internal static extern void Copy(Array sourceArray, int sourceIndex, Array destinationArray, int destinationIndex, int length, bool reliable);
看完之后,我有些困惑。我困惑的根源是
extern
修饰符,它的意思是(MSDN链接):但是,方法声明也用
MethodImplOptions.InternalCall
属性修饰,该属性指示(MSDN链接):谁能解释这个看似明显的矛盾?
最佳答案
我会在leppie's帖子上发表评论,但是它有点长了。
我目前正在实验CLI的实现。在许多情况下,如果不了解内部如何实现虚拟机,就无法实现公开的方法(或属性)。一个示例是OffsetToStringData,它要求了解内存管理器如何分配字符串。
对于这样的情况,没有C#代码表示该方法,则可以在JIT流程内部以特殊方式处理对方法的每次调用。在此处作为示例,在将call
字节码传递给 native 代码生成器之前,将其替换为ldc.i4
(加载常数整数)。 InternalCall
标志的意思是“运行时本身以特殊方式对待此方法的主体。”可能有或没有实际的实现-在我的代码中,在某些情况下,JIT将调用视为intrinsic。
在其他情况下,JIT可能具有可用于方法的大量优化的特殊信息。一个示例是Math
方法,即使这些can be implemented in C#,指定InternalCall
以使其有效地成为内在函数也具有显着的性能优势。
在C#中,方法必须具有主体,除非它是abstract
或extern
。 extern
表示一般性的“您可以从C#代码中调用此方法,但实际上是在其他地方定义的”。当JIT到达对extern
方法的调用时,它将查找在何处找到主体并根据结果以不同的方式表现。
DllImport
属性指示JIT创建一个P/Invoke存根以调用 native 代码实现。 InternalCall
标志指示JIT以自定义方式对待调用。 关于c# - 具有InternalCall属性的C#内部静态外部-内部还是外部?,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/1211462/