带有InternalCall属性的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);
看完这个之后,我有点困惑。 我混淆的来源是extern
修饰符,意思是(MSDN链接):
extern修饰符用于声明外部实现的方法。
但是,方法声明也使用MethodImplOptions.InternalCall
属性进行了修饰,该属性表示(MSDN链接):
指定一个内部呼叫。 内部调用是对公共语言运行时本身实现的方法的调用。
任何人都可以解释这个看似明显的矛盾吗?
我只是会对leppie的帖子发表评论,但它会变得有点长。
我目前正在开发一个实验性的CLI实现。 在很多情况下,如果没有关于虚拟机如何在内部实现的知识,公开暴露的方法(或属性)就无法实现。 OffsetToStringData就是一个例子,它需要知道内存管理器如何分配字符串。
对于这样的情况,如果没有C#代码来表示该方法,则可以用JIT进程内部的特殊方式来对待每个对该方法的调用。 作为一个例子,在将它传递给本地代码生成器之前,用ldc.i4
(加载常量整数)来替换call
字节代码。 InternalCall
标志表示“该方法的主体由运行时本身以特殊方式处理”。 可能有也可能没有实际的实现 - 在我的代码中的几个例子中,调用被JIT视为内在。
还有其他一些情况下,JIT可能有特殊的信息可以对方法进行大量的优化。 一个例子是Math
方法,尽管这些方法可以在C#中实现,但指定InternalCall
以使它们有效地实现内部函数具有显着的性能优势。
在C#中,一个方法必须有一个主体,除非它是abstract
或extern
。 extern
意味着一个通用的“你可以从C#代码中调用这个方法,但它的主体实际上是在别处定义的。” 当JIT到达一个extern
方法的调用时,它会查找在哪里找到主体,并根据结果以不同的方式运行。
DllImport
属性指示JIT使P / Invoke存根调用本地代码实现。 InternalCall
标志指示JIT以自定义的方式处理该呼叫。 InternalCall
是由框架提供的。
extern
说你不提供代码。
extern
可以用于2个一般情况,比如上面,或者用p / invoke。
使用p / invoke,你只需告诉方法在哪里得到实现。
链接地址: http://www.djcxy.com/p/82147.html