何时在不使用属性的情况下使用extern关键字是否合适?

我今天重读了一些.Net文档,当时我注意到extern关键字文档的第一部分声称:

extern修饰符用于声明从外部实现的方法。 当您使用Interop服务调用非托管代码时,extern修饰符的常见用法是使用DllImport属性。

引起我注意的是该文档声明extern “常见用途”是它与DllImport属性一起使用。 这意味着还有其他用例,不需要DllImport。 我不必将许多外部的非托管库集成到我的应用程序中,但在所有情况下,链接的方法都是使用DllImport定义的。

我通过Google和MSDN搜索了多个查询,但是我找不到关于何时使用extern关键字的情况或解释,而没有将方法定义为从非托管dll导入的外部方法。

如何以及何时使用extern关键字而不在方法定义中定义[DllImport(...)]属性?

请注意,这不是特定于在定义别名时使用extern 。 这是关键字的不同用法,并且在MSDN C#语言参考中的不同文章中概述了该案例。

我使用它的一个案例是,如果我是Microsoft开发人员实现对C​​LR本身定义的方法的调用。 就像在GC._WaitForFullGCApproach一样:

 [MethodImpl(MethodImplOptions.InternalCall)] private static extern int _WaitForFullGCApproach(int millisecondsTimeout); 

注意:没有DllImport 。 当然这是作弊 – 这仍然是对非托管方法的调用,而不是对DLL的显式引用。 但是凡人不能调用这样的代码,因为它仅在mscorlib程序集中有效。

InternalCall另一个应用是为COM生成的互操作类型:

 namespace Microsoft.Office.Interop.Excel { [DefaultMember("_Default")] [ClassInterface(0)] [ComSourceInterfaces("Microsoft.Office.Interop.Excel.AppEvents\0")] [Guid("00024500-0000-0000-C000-000000000046")] [TypeLibType(2)] [ComImport] public class ApplicationClass { // ... [DispId(302)] [MethodImpl(MethodImplOptions.InternalCall)] public virtual extern void Quit(); // ... } } 

这些属性允许运行时将方法调用解析为对COM接口的调用。 显然,使用InternalCallmscorlib之外有效的。 你通常不会自己在C#中编写这样的代码; 当您添加COM类型库作为参考时,它是按需生成的。

C#语言规范比MSDN更详细:

extern修饰符通常与DllImport属性(第17.5.1节)结合使用,允许外部方法由DLL(动态链接库)实现。 执行环境可以支持其他机制,由此可以提供外部方法的实现。

从实现的角度来看,标记方法extern仅具有将方法的RVA(相对虚拟地址)设置为0的效果,将其标​​记为没有实现。 DllImport (和MethodImpl )之类的属性是向运行时描述如何定位方法的实际实现所必需的。 这在ECMA-335的第I.9.4节中描述,“方法实现元数据”( DllImportInternalCall似乎是当前可用的唯一方法)。

C#编译器允许您将方法标记为extern而不使用任何属性来指示实现的位置,但任何具有此类方法的类型都将在运行时导致TypeLoadException