Read the latest post on the subject:
C# Static Interfaces -
Take 3
No DDD today, let’s talk a bit about our favorite language after a short
night (I should really tell my neighbors that 3am is not the good time to move
their furniture all around the flat).
You can find requests for static methods in interfaces all over the internet..
But there are good reasons not to.
According to Eric Lippert, the main reasons is the difference in inheritance
between static methods and instance method du to the absence of shared slots
between static methods.
Mixing both static methods and instance methods in interfaces would lead to
a real nightmare when you try to understand what really happens.
But why does this question arise so often then ? What’s really needed ?
Static classes as type instances
Let’s take a simple class with both static and instance members :
class
Sample
{
// static part
private static
int count;
public static
int Count { get { return count; }
}
// instance part
private readonly
string name;
public Sample(string
name) { this.name = name; }
public void Method()
{
count++;
Console.WriteLine("Total
count {0} incremented by {1}", count, name);
}
}
Here, Count is a static Property. Static part is different from instance
part in that static part exist only once per type.
But we could see static part as being an object with reference is type
name.
Why would these object not have interfaces ?
Let refactor this a bit :
public
class Sample2
{
public sealed
class Sample2Class
{
internal int count;
public int Count {
get { return
count; } }
}
public static
readonly Sample2Class Class = new Sample2Class();
private readonly
string name;
public Sample2(string
name)
{
this.name = name;
}
public void Method()
{
Class.count++;
Console.WriteLine("Total
count {0} incremented by {1}", Class.count, name);
}
}
Here, the only static member is Class, that acts as a singleton for the
type. Note that I had to change the count modifier to internal. The behavior is
not the same, but it’s conceptually equivalent.
We can make something less extreme :
public
class Sample3
{
private static
int count;
public static
int Count { get { return count; }
}
private readonly
string name;
public static
readonly Sample3Class Class = new Sample3Class();
public sealed
class Sample3Class
{
public int Count {
get { return
Sample3.Count; } }
}
public Sample3(string
name) { this.name = name; }
public void Method()
{
count++;
Console.WriteLine("Total
count {0} incremented by {1}", count, name);
}
}
Here, we added only a proxy of public methods and properties on the
singleton class.
We could define an interface that would be implemented by Sample3Class that
would provide the missing slot concept that Eric Lipperts talk
about.
We can also see here that there is no point mixing static and instance
method in interface since inheritance rules differs.
Static Interface
Imagination at work. Let’s define static interface as we can define static
classes :
public
static interface ICountable
{
static int Count {
get; }
}
and implement it on our sample :
public
class Sample4 : ICountable
{
private static
int count;
public static
int Count { get { return count; }
}
private readonly
string name;
public Sample4(string
name) { this.name = name; }
public void Method()
{
count++;
Console.WriteLine("Total
count {0} incremented by {1}", count, name);
}
}
The C# compiler would be responsible for creating a singleton stub in the
class. Since the goal is to provide a function table, this could also be
handled at a lower level by the CLI.
Now, we can have interesting language extensions.
Static member access in generics
Let see it in action :
public static bool
IsInstanciated<T>() where T:
ICountable
{
return T.Count != 0;
}
There is no ambiguity when using this method since values of parameter T are
known at compilation time. The C# compiler could replace the static call with a
interface call on the proxy. On a CLI version, the JIT compiler could resolve
it once and for all and emit a static call. Use of a child type whose parent
type implements the interface should not be allowed, the compiler could report
this.
This could be combined with an extension method syntax to provide extension
methods on types :
public static bool
IsInstanciated(static ICountable type)
{
return type.Count != 0;
}
This one is a bit twisted, and I would gracefully admit changes in the
syntax, but the point is that it would enable on type/classes the same kind of
thing that Linq offers with interfaces : put the minimum set of methods in
interface, then add lots of features around interface with extension
methods.
Back to reality
Ok, I should sleep at night, but who knows, it’s perhaps useful.
If anyone sees other applications… just drop a comment.