157

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();
}
John Smith
  • 7,243
  • 6
  • 49
  • 61
Jon
  • 38,814
  • 81
  • 233
  • 382
  • 5
    Maybe you can do it with extension methods: http://stackoverflow.com/questions/1243921/c-sharp-interface-static-method-call-with-generics – hcb Feb 23 '12 at 14:49
  • 2
    Interface methods are meant to be implemented as instance methods. If you want replicate the methods of an static api to an interface, you can create a class that implement this interface, just delegating all calls to the real static api. – Jone Polvora Mar 30 '22 at 23:56

12 Answers12

160

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.

Danny Varod
  • 17,324
  • 5
  • 69
  • 111
  • 38
    For anyone wondering why anyone would want to do this, its particularly useful when writing unit/integration tests for legacy code that implements static methods. – Dezzamondo Nov 22 '17 at 12:15
  • 1
    This technique worked very well for implementing a quick RESTful API that needed to persist data but couldn't use a database. The implementation was only working with in-memory C# objects so there was no place to store data, but using a static property alleviated the need for an in-memory database using EF Core or SQLite. – gware Sep 25 '20 at 13:29
  • 2
    @gware not the way I would recommend solving this - try injecting the in-memory data structure into the non-static class' constructor instead. Also, you can have a regular property access a static field (also not recommended). – Danny Varod Feb 11 '21 at 09:29
132

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

UPDATE:

Also, I should note in C# 11 you can have static abstract members too, and abstract members don't need default implementations

public interface IMyInterface
{
    static abstract string GetHello();
    static abstract void WriteWorld();
}

more info about static abstracts

AliReza Sabouri
  • 4,355
  • 2
  • 25
  • 37
  • 5
    It seems like static members in interfaces are pretty useless because you can't access them by interface instance. At least in C# 8. – Pavel Sapehin Feb 17 '20 at 08:12
  • 9
    as an Interface implementation point of view, your right. it is useless. but this way at least you are sure to have an implemented method on every class that is using this interface. (this is kind of optional implementation for interfaces) – AliReza Sabouri Feb 17 '20 at 14:27
  • these seem not to specify a "static interface" but are rather static members that belong to the interface. – Dave Cousineau Aug 20 '22 at 21:36
72

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.

davisoa
  • 5,407
  • 1
  • 28
  • 34
  • 79
    -1 for saying `An interface is a contract, not an implementation.` - that's true, but completely irrelevant (*non sequitur*) here, since *static method is not a part of implementation itself* - implementation, by definition, is based on *data*, which is, in turn, *inaccessible* for static members. `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.` - bear in mind that `static` members are usually *utility methods*. –  Dec 28 '15 at 16:16
  • 3
    I understand and agree with your statements, and I feel your comment is important context as well. Although. when designing an interface, one should think about it as a contract, which implies static methods do not apply. I figured I should leave it there to help some people understand an interface's purpose. Does the community feel it should be removed? – davisoa Dec 02 '16 at 15:54
  • 4
    I partially agree that `An interface is a contract, not an implementation` is useless, sometimes a bit contextualization really helps. And I totally agree with `static method is not a part of implementation itself `, static methods **have** a implementation, they become part of implementation only if used as implementation in the implementation of another method. However my dictionary is based on what learned, as far as I know, terminology really varies also depending on programming language. Static methods cant be interfaces because there can be anyway only 1 implementation. – CoffeDeveloper Dec 06 '16 at 18:24
  • Imagine I have an `IPerson` contract that states that `GetCountry` will give the person's origin country name... `FrenchPerson` entities will all say "France" and `GermanPerson` will all say "Germany", also useful when different types of entities shares the same (Data) Table, like MS Azure one, say `Connection`, `Post` and `Comment` are stored in the `Users` AzureTable, so tree entities have a shared info, `IUsers` could have `GetTableName` static method... – serge Aug 22 '17 at 16:50
  • 2
    @vaxquis - IMHO, "its a contract" would be relevant if the sentence were reworded: `An interface is a contract *for instances*. Static members are part of the type; this reworded sentence says (correctly) that they have no meaning in an instance contract. So I think the problem is merely imprecise wording, not a non sequitur. – ToolmakerSteve Feb 02 '18 at 16:17
  • 1
    Thanks for the suggestion, I updated the answer as you suggested – davisoa Mar 22 '18 at 18:31
  • Purpose of interface is polymorhpism. Many classes (or subclasses) can implement interface methods in their own ways. To avoid compilation errror, this strategy is very bad. – Gauravsa Aug 11 '18 at 02:02
20

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.

leppie
  • 115,091
  • 17
  • 196
  • 297
  • 10
    For reference, `CLS Rule 19: CLS-compliant interfaces shall not define static methods, nor shall they define fields.` It goes on to say that it is okay for CLS compliant consumers to reject these kinds of interfaces. I tried around a year ago to call a static method on an interface and the C# compiler would not compile it. – Christopher Currens Nov 08 '13 at 00:58
  • Further to @ChristopherCurrens note about the CLS: `Common Language Specification (CLS) is a set of basic language features that .Net Languages needed.... When there is a situation to communicate Objects written in different .Net Complaint languages , those objects must expose the features that are common to all the languages.` It makes sense that if the CLS is about interoperability across different .NET languages, and C# doesn't allow static members on an interface, then the CLS would forbid them as well, to ensure libraries in other .NET languages can be called from C#. – Simon Elms Jan 04 '17 at 23:42
15

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;
Christian Findlay
  • 6,770
  • 5
  • 51
  • 103
  • 1
    these are static members that live in the interface for convenience (for help with default interface implementations), but they are not a part of the actual "interface" and are not applied to implementations of the interface. – Dave Cousineau Aug 20 '22 at 21:40
7

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.

Tamas Hegedus
  • 28,755
  • 12
  • 63
  • 97
  • In the video you linked to, Mads said generic-interfaces, roles, and type-extensions are something _they're only considering_ - he didn't say it was confirmed. I think you should change "C# "Ten" is going to allow static members on interfaces," to be less assertive. – Dai Apr 21 '21 at 01:21
7

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.

Wim
  • 378
  • 2
  • 6
  • 14
  • It's confusingly written, but my understanding of the above documentation (at 26th May 2022) is that this is available as a preview feature in C#10 but is currently slated for proper release in C#11. It's also presented as a C#11 feature in [Mads Torgersen's Build talk on C#11 features](https://mybuild.microsoft.com/en-US/sessions/34024242-36f5-4e37-b2fe-5b040ec55a3e). – ADBailey May 26 '22 at 15:44
7

Starting from C# 11 and .NET 7, it is possible to have static members in interfaces without having to provide a default implementation.

Here is how you define the interface.

interface IDoSomething
{
    static abstract void DoSomething();
}

And here is how you make a class implement this interface.

class DoerImplementation : IDoSomething
{
    public static void DoSomething()
    {
        // Method implementation goes here
    }
}

You will probably specify the implementation to be used using a generic type parameter like so.

class MyClass
{
    void MyMethod<T>() where T : IDoSomething
    {
        T.DoSomething();
    }

    void MyOtherMethod()
    {
        MyMethod<DoerImplementation>();
    }
}

For more information about static virtual members in interfaces, see this Microsoft Learn article.

Bassem
  • 2,736
  • 31
  • 13
5

You could invoke it with reflection:

MyInterface.GetType().InvokeMember("StaticMethod", BindingFlags.Static | BindingFlags.Public | BindingFlags.InvokeMethod, null, null, null);
John Koerner
  • 37,428
  • 8
  • 84
  • 134
  • 5
    And if you don't have an instance of MyInterface you can use "typeOf(MyInterface)" instead of "myInterface.GetType()". – RenniePet Aug 23 '16 at 20:52
  • Seemed like a good idea at the time, and I may continue to do it via reflection, but one little warning: it does become more problematic if the program gets obfuscated such that method StaticMethod gets renamed. – RenniePet Oct 17 '16 at 04:47
  • 1
    @RenniePet: You could partially deal with the StaticMethod renaming by using nameof(StaticMethod) instead. It MIGHT help with an obfuscator depending on how it renames. If you do it this way you'd at least see a compile time error though. – Brent Rittenhouse Jul 28 '17 at 19:35
  • 1
    Reflection is too extreme for this case – Stepagrus Apr 05 '19 at 12:23
2

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();
    }
}
Community
  • 1
  • 1
Justin Pihony
  • 66,056
  • 18
  • 147
  • 180
1

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"

Walter Verhoeven
  • 3,867
  • 27
  • 36
-1

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

  • Your answer could be improved with additional supporting information. Please [edit] to add further details, such as citations or documentation, so that others can confirm that your answer is correct. You can find more information on how to write good answers [in the help center](/help/how-to-answer). – Community Jan 11 '22 at 17:54