具有InternalCall属性的C#内部静态extern - 内部还是外部?

Cra*_*gTP 34 .net c#

在我问的另一个问题中,出现了一条评论,表明.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);
Run Code Online (Sandbox Code Playgroud)

看了这个之后,我有点困惑.我混淆的来源是extern修饰符,意思是(MSDN链接):

extern修饰符用于声明从外部实现的方法.

但是,方法声明也用一个MethodImplOptions.InternalCall属性来装饰,它表示(MSDN链接):

指定内部调用.内部调用是对在公共语言运行时本身内实现的方法的调用.

任何人都可以解释这个看似明显的矛盾吗?

Sam*_*ell 50

我本来会评论leppie的帖子,但它有点长.

我目前正在开发一个实验性的CLI实现.在许多情况下,如果不了解内部如何实施虚拟机,则无法实现公开的方法(或属性).一个例子是OffsetToStringData,它需要知道内存管理器如何分配字符串.

对于这样的情况,如果没有C#代码来表达方法,则可以在JIT进程内部以特殊方式处理对方法的每次调用.作为示例,在将call字节代码ldc.i4传递给本机代码生成器之前,用(加载常量整数)替换字节代码.该InternalCall标志表示"该方法的体在由运行时自身一种特殊的方式进行处理." 可能有也可能没有实际的实现 - 在我的代码中的几种情况下,调用被JIT 视为内在的.

在其他情况下,JIT可能具有可用的特殊信息,允许对方法进行大量优化.一个例子是这些Math方法,即使这些方法可以在C#中实现,指定InternalCall使它们有效地具有内在性也具有显着的性能优势.

在C#中,方法必须有一个体,除非它是abstractextern.这extern意味着一般的"你可以用C#代码调用这个方法,但它的主体实际上是在其他地方定义的." 当JIT到达对extern方法的调用时,它会查找找到正文的位置,并根据结果以不同的方式运行.

  • DllImport属性指示JIT创建P/Invoke存根以调用本机代码实现.
  • InternalCall标志指示JIT以自定义方式处理呼叫.
  • (还有其他一些,但是我没有使用它们的例子.)


lep*_*pie 17

InternalCall 框架提供的手段.

extern 说你没有提供代码.

extern 可以在两种一般情况下使用,例如上面的,或者使用p/invoke.

使用p/invoke,您只需告诉方法获取实现的位置.