我今天重读了一些.Net文档,当时我注意到extern
keywords documentation声明的第一部分:
extern修饰符用于声明从外部实现的方法。 当您使用Interop服务调用非托管代码时,extern修饰符的常用 与DllImport属性一起使用。
引起我注意的是该文件指出"一种常见用途" extern
的含义是它与DllImport属性一起使用。这意味着还有其他用例不需要DllImport。我不必将许多外部的非托管库集成到我的应用程序中,但在所有情况下,链接的方法都是使用DllImport定义的。
我已经通过Google和MSDN搜索了多个查询,我无法找到关于何时使用extern
关键字的案例或解释,而没有将该方法定义为从外部方法导入unmanaged dll。
如何在不定义方法定义的extern
属性的情况下,如何以及何时使用[DllImport(...)]
关键字?
请注意,这不是特定于在定义别名时使用extern
。这是关键字的不同用法,在MSDN C#语言参考中该情况为outlined in a different article。
答案 0 :(得分:8)
我使用它的一个案例是,如果我是Microsoft开发人员实现对CLR本身定义的方法的调用。就像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接口的调用。显然,InternalCall
的使用在mscorlib
之外有效。您通常不会自己在C#中编写此类代码;当您添加COM类型库作为参考时,它是按需生成的。
C#语言规范比MSDN更详细:
extern
修饰符通常与DllImport
结合使用 属性(第17.5.1节),允许外部方法实现 DLL(动态链接库)。执行环境可能会支持 外部方法的实现可以是其他机制 提供。
从实现的角度来看,标记方法extern
仅具有将方法的RVA(相对虚拟地址)设置为0的效果,将其标记为没有实现。像DllImport
(和MethodImpl
)这样的属性是向运行时描述如何定位方法的实际实现所必需的。这在ECMA-335的第I.9.4节中描述,“方法实施元数据”(以及DllImport
和InternalCall
似乎是目前可用的唯一方式。)
C#编译器允许您将方法标记为extern
而不使用任何属性来指示实现的位置,但任何具有此类方法的类型都将导致{ {1}}在运行时。