How can I implement static methods on an interface?

C#.NetInterface

C# Problem Overview


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();
}

C# Solutions


Solution 1 - C#

Interfaces can't have static members and static methods cannot 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 - C#

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 - C#

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 - C#

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.

Solution 5 - C#

C# 8 Allows Static Members on Interfaces

> 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;

Solution 6 - C#

They are considering adding some of those features in a future version of C# called C# "Ten". These theoretical features might allow static members on interfaces, alongside with roles. It would be huge step forward, it would allow generic operator overloading too, without any use of reflection. Here is an example snippet how it is planned to work, 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.

Solution 7 - C#

You could invoke it with reflection:

MyInterface.GetType().InvokeMember("StaticMethod", BindingFlags.Static | BindingFlags.Public | BindingFlags.InvokeMethod, null, null, null);

Solution 8 - C#

As to why you cannot have a static method on an interface: https://stackoverflow.com/questions/259026/why-doesnt-c-sharp-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();
    }
}

Solution 9 - C#

You can use simply:

     public interface MyInterface<T>
     {
         T Method();
     }
     
     public class MyClass<T> : MyInterface<T>
     {
         public T Method() => //Your implementation   
     }

So you use:

    var result = new MyClass<T>().Method();

The static class is a class where you dont need to instantiate it. But C# allow this kind of thing that for me it´s simple and works (most important). Sure you need to avoid implement anything inside Method() that´s change info in your class, since after this call, the class will vanish (I Hope).

Solution 10 - C#

I see no issues other than the compiler thinking that I should not do this. C# can't inherit from more than one base class, real bummer when you are used to be able to do this, frontally you can do several interfaces, so I abuse that to sneak in the features I need ;-)

You should check for null etc however here is a simplified version that implements Parse to get a class from a web service or database

/// <summary>
/// Implements parse
/// </summary>
/// <typeparam name="T">the type to parse</typeparam>
public interface IParse<T>
{ 
    /// <summary>
    /// implements parse from string to type
    /// </summary>
    /// <param name="text">value to parse</param>
    /// <returns></returns>
    static T Parse(string text)=>JsonConvert.DeserializeObject<T>(text, settings:new JsonSerializerSettings() { ConstructorHandling= ConstructorHandling.AllowNonPublicDefaultConstructor });

    /// <summary>
    /// implements parse from string to type
    /// </summary>
    /// <param name="text">value to parse</param>
    /// <param name="settings">the settings to us</param>
    /// <returns></returns>
    static T Parse(string text, JsonSerializerSettings settings) =>JsonConvert.DeserializeObject<T>(text, settings);
}

Then I just call the interface in code that has List as the return value.

Here is a snip where I read JSON from the database as populating it to a type that has Json implemented

//some plugging code

using (var reader = cmd.ExecuteReader(behavior: CommandBehavior.CloseConnection | CommandBehavior.SingleResult))
{
    if (reader.HasRows)
    {
        while (reader.Read())
        {
            rows++;
            try
            {
                var json = reader.GetString(0);

                result.Add(IParse<T>.Parse(json));
            }
            catch
            {
                failed++;
            }
        }
    }
}
//other plugging code

With >ver version 8 you have the default implementation so "pandora's box is open"

Solution 11 - C#

This post is old but there are changes in C# since the last relevant post.

Pre C#8

Static methods are not a thing

Pre C#10/11

Static methods/properties can be defined but must be implemented:

public interface MyInterfaceWithStaticMethod 
{
    public static String HelloWorld() => "Hello world";
}

C#10/11

At the time of writing it is known that the feature of static interface will come to C# but the version is unclear to me.

According to this article you can now try out 'static abstract members in interfaces' with a preview of C#10 .NET6

On the other hand according to this article it will only be released in C#11.

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionJonView Question on Stackoverflow
Solution 1 - C#Danny VarodView Answer on Stackoverflow
Solution 2 - C#davisoaView Answer on Stackoverflow
Solution 3 - C#AliReza SabouriView Answer on Stackoverflow
Solution 4 - C#leppieView Answer on Stackoverflow
Solution 5 - C#Christian FindlayView Answer on Stackoverflow
Solution 6 - C#Tamas HegedusView Answer on Stackoverflow
Solution 7 - C#John KoernerView Answer on Stackoverflow
Solution 8 - C#Justin PihonyView Answer on Stackoverflow
Solution 9 - C#Fernando RodriguesView Answer on Stackoverflow
Solution 10 - C#Walter VerhoevenView Answer on Stackoverflow
Solution 11 - C#WimView Answer on Stackoverflow