How can I implement static methods on an interface?

I have a 3rd party C++ DLL that I call from C#.

The methods are static.

I want to abstract it out to do some unit testing so I created an interface with the static methods in it but now my program errors with:

The modifier 'static' is not valid for this item

MyMethod cannot be accessed with an instance reference; qualify it with a type name instead

How can I achieve this abstraction?

My code looks like this

private IInterfaceWithStaticMethods MyInterface;

public MyClass(IInterfaceWithStaticMethods myInterface)
{
  this.MyInterface = myInterface;
}

public void MyMethod()
{
  MyInterface.StaticMethod();
}

Solution 1:

Interfaces can't have static members and static methods can not be used as implementation of interface methods.

What you can do is use an explicit interface implementation:

public interface IMyInterface
{
    void MyMethod();
}

public class MyClass : IMyInterface
{
    static void MyMethod()
    {
    }

    void IMyInterface.MyMethod()
    {
        MyClass.MyMethod();
    }
}

Alternatively, you could simply use non-static methods, even if they do not access any instance specific members.

Solution 2:

You can't define static members on an interface in C#. An interface is a contract for instances.

I would recommend creating the interface as you are currently, but without the static keyword. Then create a class StaticIInterface that implements the interface and calls the static C++ methods. To do unit testing, create another class FakeIInterface, that also implements the interface, but does what you need to handle your unit tests.

Once you have these 2 classes defined, you can create the one you need for your environment, and pass it to MyClass's constructor.

Solution 3:

You can define static methods in c# 8 but you must declare a default body for it.

public interface IMyInterface
{
      static string GetHello() =>  "Default Hello from interface" ;
      static void WriteWorld() => Console.WriteLine("Writing World from interface");
}

or if you don't want to have any default body simply throw an exception:

public interface IMyInterface
{
      static string GetHello() =>  throw new NotImplementedException() ;
      static void WriteWorld() => throw new NotImplementedException();
}

Solution 4:

Static members are perfectly legal in the CLR, just not C#.

You could implement some glue in IL to link up the implementation details.

Not sure if the C# compiler would allow calling them though?

See: 8.9.4 Interface type definition ECMA-335.

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).

Similarly, an interface type definition shall not provide implementations for any methods on the values of its type. However, an interface type definition can—and usually does—define method contracts (method name and method signature) that shall be implemented by supporting types. An interface type definition can define and implement static methods (see §8.4.3) since static methods are associated with the interface type itself rather than with any value of the type.