I was re-reading through some .Net documentation today when I noticed that the first portion of the extern
keywords documentation claims:
The extern modifier is used to declare a method that is implemented externally. A common use of the extern modifier is with the DllImport attribute when you are using Interop services to call into unmanaged code.
What caught my attention was that the document states that "a common use" of extern
is that it is used with the DllImport attribute. This implies that there are other use-cases where DllImport is not required. I've not had to integrate many external, non-managed libraries into my applications but in all cases the linked methods were defined with DllImport.
I've searched multiple queries through Google and MSDN and I can't find a case or explanation of when the extern
keyword would be used without defining the method as an external method import from an unmanaged dll.
How, and when, would you use the extern
keyword without defining the [DllImport(...)]
attribute on the method definition?
Please note, this is not specific to using extern
when defining aliases. That is a different use of the keyword and that case is outlined in a different article within the MSDN C# language reference.
One case where I'd use it is if I were a Microsoft developer implementing a call to a method defined in the CLR itself. Like in GC._WaitForFullGCApproach
:
[MethodImpl(MethodImplOptions.InternalCall)]
private static extern int _WaitForFullGCApproach(int millisecondsTimeout);
Note: no DllImport
. Of course this is cheating a bit -- this is still a call to an unmanaged method, just not with an explicit reference to a DLL. Mere mortals cannot invoke such code, though, since it's valid only in the mscorlib
assembly.
Another application of InternalCall
is in interop types generated for 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();
// ...
}
}
The attributes allow the runtime to resolve the method call as an invocation to a COM interface. This use of InternalCall
is valid outside mscorlib
, obviously. You would not typically write such code in C# yourself; it's generated on demand when you add a COM type library as a reference.
The C# language specification goes into slightly more detail than the MSDN:
The extern
modifier is typically used in conjunction with a DllImport
attribute (§17.5.1), allowing external methods to be implemented by
DLLs (Dynamic Link Libraries). The execution environment may support
other mechanisms whereby implementations of external methods can be
provided.
From an implementation standpoint, marking a method extern
only has the effect of setting the RVA (relative virtual address) of the method to 0, marking it as having no implementation. Attributes like DllImport
(and MethodImpl
) are necessary to describe to the runtime how to locate the method's actual implementation. This is described in secion I.9.4 of ECMA-335, "Method implementation metadata" (and DllImport
and InternalCall
seem to be the only ways currently available).
The C# compiler will allow you to mark a method as extern
and not use any attribute to indicate where the implementation lives, but any type with such a method will result in a TypeLoadException
at runtime.