我在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#中,方法必须具有主体,除非它是abstractexternextern表示一般性的“您可以从C#代码中调用此方法,但实际上是在其他地方定义的”。当JIT到达对extern方法的调用时,它将查找在何处找到主体并根据结果以不同的方式表现。

  • DllImport属性指示JIT创建一个P/Invoke存根以调用 native 代码实现。
  • InternalCall标志指示JIT以自定义方式对待调用。
  • (还有一些其他例子,但我没有脑海中可以使用的示例。)
  • 关于c# - 具有InternalCall属性的C#内部静态外部-内部还是外部?,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/1211462/

    10-12 07:39
    查看更多