C#内部静态外部与InternalCall属性 - 内部或外部?

问题描述:

another question我问,一个评论出现,指出.NET框架的Array.Copy方法使用非托管代码。我去Reflector挖掘,发现签名Array.Copy方法重载的一个被定义为这样:C#内部静态外部与InternalCall属性 - 内部或外部?

[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链路):

的extern修饰符用于声明 被实现 外部的方法。

然而,该方法声明还装饰有一个MethodImplOptions.InternalCall属性,其指示(MSDN链路):

指定内部呼叫。内部呼叫是对方法 的调用,该方法在通用的 语言运行时本身内实施。

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

我刚才对leppie's发表了评论,但是它有点长了。

我目前正在研究一个实验性的CLI实现。在很多情况下,如果没有关于虚拟机如何在内部实现的知识,公开暴露的方法(或属性)就无法实现。一个例子是OffsetToStringData,它需要知道内存管理器如何分配字符串。

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

还有其他一些情况下,JIT可能有特殊的信息可用,可以对方法进行重度优化。一个例子是Math方法,其中即使这些can be implemented in C#,指定InternalCall使它们有效地具有内在性具有显着的性能优点。

在C#中,一个方法必须有一个主体,除非它是abstractexternextern意味着一个通用的“你可以从C#代码调用这个方法,但它的主体实际上是在其他地方定义的。”当JIT接到对extern方法的调用时,它会查找哪里可以找到主体,并根据结果以不同的方式运行。

  • DllImport属性指示JIT制作P/Invoke存根以调用本机代码实现。
  • InternalCall标志指示JIT以自定义方式处理呼叫。
  • (有一些人,但我没有把我的头顶部供他们使用的例子。)

InternalCall表示由框架提供。

extern说你不提供代码。

extern可用于2种一般情况,如上述,或与p/invoke。

使用p/invoke,您只需告诉方法从哪里获得实现。

+0

@leppie - 我想我可能标志着双方你和280Z28的回答,因为你作为公认的”都是正确的。但是,我认为280Z28的答案能够更清楚地说明问题,并帮助我更好地理解,但是,非常感谢您的努力。 – CraigTP 2009-07-31 12:52:54