Why shouldn't C#(or .NET) allow us to put a static/shared method inside an interface?

夙愿已清 提交于 2019-11-28 12:14:33

The idea of an interface is to represent a contract, not implementation.

I can't remember offhand whether IL actually does allow static methods with implementations in interfaces - I've a sneaky suspicion that it does - but that muddies the concept somewhat.

I can see your point - it's sometimes useful to know what helper methods are available which are connected with an interface (and extension methods are particularly relevant there) but I would personally want to put those in a separate class anyway, just to keep the mental model clean.

I've run into this several times and did some research. The sad part is, IL actually supports this. I got so frustrated with this I wrote a blog post about it. You can find it here.

Anton Gogolev

For your purpose, it will be much better to decouple plugin interface from plugin loader implementation: this will make your design much less coupled and more cohesive (thus reducing complexity).

As for "static methods in interface", see this.

And as a sidenote: you don't really want to invent yet another plugin architecture: take a look at MEF.

Check out my blog entry on static methods implemented in interfaces (sorry for the shameless self reference)

[removed broken link http:/... ]

dotnetjunkies site is poked by totaldevpro ... so the google cached version is the only one available

Edit: I pasted a cached version below I found:

[...]

Use ILAsm to compile the following:

.assembly extern mscorlib {
 .publickeytoken = (B7 7A 5C 56 19 34 E0 89 )                         
 .ver 2:0:0:0
}

 .assembly MaLio.StaticInterface{
 .hash algorithm 0x00008004
 .ver 0:1:0:0
}

.module MaLio.StaticInterface.dll
.imagebase 0x00400000
.file alignment 0x00001000
.stackreserve 0x00100000
.subsystem 0x0003      
.corflags 0x00000001   

.class interface public abstract auto ansi MaLio.IMyInterface {

 .method public hidebysig newslot abstract virtual instance void  DoInstanceWork() cil managed  {
 } 

 .method public hidebysig static void  DoStaticWork() cil managed  {
     ldstr      "Static"
     call       void [mscorlib]System.Console::WriteLine(string)
     ret
 } 
} 

.class public auto ansi beforefieldinit MaLio.MyClass extends [mscorlib]System.Object implements MaLio.IMyInterface {

 .method public hidebysig newslot virtual final instance void  DoInstanceWork() cil managed  {
     ldstr      "Instance"
     call       void [mscorlib]System.Console::WriteLine(string)
     ret
 } 

 .method public hidebysig specialname rtspecialname instance void  .ctor() cil managed {
     ldarg.0
     call       instance void [mscorlib]System.Object::.ctor()
     ret
 } 
} 

This code then can be called

System.Type myInterface = typeof(MaLio.IMyInterface);
// show that we really are dealing with an interface 
if (myInterface.IsInterface) {
   System.Reflection.MethodInfo staticMethod = myInterface.GetMethod("DoStaticWork");
   staticMethod.Invoke(null, null);
}

Intellisense (VS) does not work here as expected. It recognized the static method as an instance method of the interface, and the code (if following the intellisense prompts) looks all in order as if it were going to compile. The C# compiler (MS C#) does not compile the code as C# does not suppport implemented static methods on interfaces, and can from C# only be invoked via reflection.

I have not tested with other IDE's such as SharpDevelop ... so have no idea as yet how it would deal with this situation.

An interface is just that, an interface. It isn't meant to be used to describe behavior. When a class implements an interface, the class just says "I promise that I provide methods/events/etc with these signatures".

What you want is an interface without the static method and an abstract base class that implements the interface and the static method. Then other classes can inherit from the base class and change the interface's method implementations. But even this is a questionable design.

static methods are associated with the type in which they are declared and not relevant for overriding. If you were able to attach a static method to an interface, you would have to reference it via the interface itself, e.g. ITaskPlugin.GetPlugins(...)

What you want to do is either:

1) Put your method in an abstract base class, as interfaces are not designed to hold implementation code, or

2) Create an extension method which applies to the interface and then you'll have access to it without having to use a base class.

An interface's purpose is to declare an object's interface through which it can be accessed. Due to the fact that this is its sole purpose, it would not make sense to allow code being placed in an interface. If you still want to add some code to an interface, you could use extension methods.

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!