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
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();
}
You could invoke it with reflection:
MyInterface.GetType().InvokeMember("StaticMethod", BindingFlags.Static | BindingFlags.Public | BindingFlags.InvokeMethod, null, null, null);
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.
Beginning with C# 8.0, an interface may define a default implementation for members. It may also define static members in order to provide a single implementation for common functionality.
interface (C# Reference)
E.g.
public interface IGetSomething
{
public static string Something = "something";
}
var something = IGetSomething.Something;
As to why you cannot have a static method on an interface: Why Doesn't C# Allow Static Methods to Implement an Interface?
However, I would suggest removing the static methods in favor of instance methods. If that is not possible, then you could wrap the static method calls inside of an instance method, and then you can create an interface for that and run your unit tests from that.
ie
public static class MyStaticClass
{
public static void MyStaticMethod()
{...}
}
public interface IStaticWrapper
{
void MyMethod();
}
public class MyClass : IStaticWrapper
{
public void MyMethod()
{
MyStaticClass.MyStaticMethod();
}
}
C# "Ten" is going to allow static members on interfaces, alongside with roles. It is a huge step forward, it will allow generic operator overloading too, without any use of reflection. Here is an example snippet how it works, using the classic monoid example, which is just jargon for saying "something that can be added". Taken directly from Mads Torgersen: C# into the Future:
interface IMonoid<T>
{
static T Zero { get; }
static T operator +(T t1, T t2);
}
public static T AddAll<T>(T[] ts) where T : IMonoid<T>
{
T result = T.Zero;
foreach (T t in ts) { result += t; }
return result;
}
role IntAddMonoid extends int : IMonoid<int>
{
public static int Zero => 0;
}
IntAddMonoid[] values = new int[] {1, 2, 4, 8, 16, 32};
int sixtyThree = AddAll<IntAddMonoid>(values); // == 63
Additional resources:
Jeremy Bytes: C# 8 interface static members
EDIT
This post originally stated interface static members will be added in C# 8.0, which is not true, I misinterpreted Mads Torgersen's words in the video. The official C# 8.0 guide does not talk about static interface members yet, but it is clear they have been working on it for quite long now.