Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Implementing Interface with static methods in C#

Tags:

c#

.net

clr

il

Suppose I have the following ILAsm code:

    .class public interface abstract ITest
    {
        .field public static int32 counter

        .method public static void StaticMethod(string str)
        {
            ldarg.0
            call void [mscorlib]System.Console::WriteLine(string)
            ret
        }

        .method public virtual abstract void InstMethod(string) { }
    }

Is it possible to define a class in C# that implements this ITest interface?

I can implement this interface in ILAsm:

    .class public TestImpl extends [mscorlib]System.Object implements ITest
    {
        .method public virtual void InstMethod(string str)
        {
            ldarg.1
            call void ITest::StaticMethod(string)
            ret
        }

        .method public specialname rtspecialname instance void .ctor()
        {
            ldarg.0
            call instance void .base::.ctor()
            ret
        }
    }

and successfully use implemented class in C# code:

        var testImpl = new TestImpl();
        testImpl.InstMethod("I'm static!"); 

But what about implementing this interface in C#?

like image 298
user2341923 Avatar asked Oct 21 '13 13:10

user2341923


2 Answers

Surprisingly (at least to me), your IL code compiles and verifies (use PEVerify for that) fine (assuming you add some .assembly directives).

And this is backed by the CLI specification (§I.8.9.4 Interface type definition):

[…] 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.

[…] An interface type definition can define and implement static methods since static methods are associated with the interface type itself rather than with any value of the type.

But doing this is not CLS-compliant:

CLS Rule 19: CLS-compliant interfaces shall not define static methods, nor shall they define fields.

And you can implement the interface in C#. The following code compiles and works fine:

class Test : ITest
{
    public void InstMethod(string s)
    { }
}

But it looks like you can't access the static field or the static method from C#.

like image 101
svick Avatar answered Oct 26 '22 05:10

svick


This is in reply to your comment that:

I see no way to get the implemented static even via reflection: var m = new Test().GetType().GetMethods(BindingFlags.Static | BindingFlags.Public); – user2341923

Remember, the declaring type of the method is an interface, so you must pull the method definition from the interface type. so roughly, I think this should work (using some linq extensions added)

var m = new Test().GetType().GetInterfaces().Where(
        i => i.IsAssignableFrom(
        typeof ITest)).First().GetMethods(
        BindingFlags.Static | BindingFlags.Public);

This would be true of any implemented members of an interface. Instance or otherwise.

like image 20
Paul Easter Avatar answered Oct 26 '22 05:10

Paul Easter