How to: Create Interfaces with Static Methods via IL?

If you try to add a static member to an interface, you will get the following error: The modifier 'static' is not valid for this item

In this case, you should create an abstract class instead of an interface, because interfaces are contracts and should not implement any methods. However, it’s still possible to do so using IL. The error above was produced because of the following rule in the CLI spec: “CLS Rule 19: CLS-compliant interfaces shall not define static methods, nor shall they define fields. (§8.9.4)”. However, if you navigate to §8.9.4, you can read the following: “Interface types are necessarily incomplete since they say nothing about the representation of the values of the interface type. For this reason, an interface type definition shall not provide field definitions for values of the interface type (i.e., instance fields), although it can declare static fields (see §8.4.3).”

Here’s how to do it in IL. For example, I added a interface called Staticable to a C# library project called TestLib, compiled it and used ildasm.exe to dump its IL, and added the following method (copied from another compiled class static method):

  1: .class interface public abstract auto ansi TestLib.Staticable
  2: {
  3:   .method public hidebysig static void  Foo() cil managed
  4:   {
  5:     .maxstack  8
  6:     IL_0000:  nop
  7:     IL_0001:  ldstr      "Hello!"
  8:     IL_0006:  call       void [mscorlib]System.Console::WriteLine(string)
  9:     IL_000b:  nop
  10:     IL_000c:  ret
  11:   } // end of method Staticable::Foo
  12: } // end of class TestLib.Staticable

Then, I compiled the modified IL using ilasm.exe: ilasm /dll /output:TestLib.dll

I used TestLib.dll as a reference to another project, and I was able to call Foo() using reflection (you have to use reflection):

  1: using TestLib;
  3: namespace Test
  4: {
  5:     class Program
  6:     {
  7:         static void Main(string[] args)
  8:         {
  9:             typeof(Staticable).GetMethod("Foo").Invoke(null, null);
  10:         }
  11:     }
  12: }