Why can't I inherit static classes?

Viewed 167133

I have several classes that do not really need any state. From the organizational point of view, I would like to put them into hierarchy.

But it seems I can't declare inheritance for static classes.

Something like that:

public static class Base
{
}

public static class Inherited : Base
{
}

will not work.

Why have the designers of the language closed that possibility?

13 Answers

Citation from here:

This is actually by design. There seems to be no good reason to inherit a static class. It has public static members that you can always access via the class name itself. The only reasons I have seen for inheriting static stuff have been bad ones, such as saving a couple of characters of typing.

There may be reason to consider mechanisms to bring static members directly into scope (and we will in fact consider this after the Orcas product cycle), but static class inheritance is not the way to go: It is the wrong mechanism to use, and works only for static members that happen to reside in a static class.

(Mads Torgersen, C# Language PM)

Other opinions from channel9

Inheritance in .NET works only on instance base. Static methods are defined on the type level not on the instance level. That is why overriding doesn't work with static methods/properties/events...

Static methods are only held once in memory. There is no virtual table etc. that is created for them.

If you invoke an instance method in .NET, you always give it the current instance. This is hidden by the .NET runtime, but it happens. Each instance method has as first argument a pointer (reference) to the object that the method is run on. This doesn't happen with static methods (as they are defined on type level). How should the compiler decide to select the method to invoke?

(littleguru)

And as a valuable idea, littleguru has a partial "workaround" for this issue: the Singleton pattern.

The main reason that you cannot inherit a static class is that they are abstract and sealed (this also prevents any instance of them from being created).

So this:

static class Foo { }

compiles to this IL:

.class private abstract auto ansi sealed beforefieldinit Foo
  extends [mscorlib]System.Object
 {
 }

Think about it this way: you access static members via type name, like this:

MyStaticType.MyStaticMember();

Were you to inherit from that class, you would have to access it via the new type name:

MyNewType.MyStaticMember();

Thus, the new item bears no relationships to the original when used in code. There would be no way to take advantage of any inheritance relationship for things like polymorphism.

Perhaps you're thinking you just want to extend some of the items in the original class. In that case, there's nothing preventing you from just using a member of the original in an entirely new type.

Perhaps you want to add methods to an existing static type. You can do that already via extension methods.

Perhaps you want to be able to pass a static Type to a function at runtime and call a method on that type, without knowing exactly what the method does. In that case, you can use an Interface.

So, in the end you don't really gain anything from inheriting static classes.

Hmmm... would it be much different if you just had non-static classes filled with static methods..?

What you want to achieve by using class hierarchy can be achieved merely through namespacing. So languages that support namespapces ( like C#) will have no use of implementing class hierarchy of static classes. Since you can not instantiate any of the classes, all you need is a hierarchical organization of class definitions which you can obtain through the use of namespaces

Although you can access "inherited" static members through the inherited classes name, static members are not really inherited. This is in part why they can't be virtual or abstract and can't be overridden. In your example, if you declared a Base.Method(), the compiler will map a call to Inherited.Method() back to Base.Method() anyway. You might as well call Base.Method() explicitly. You can write a small test and see the result with Reflector.

So... if you can't inherit static members, and if static classes can contain only static members, what good would inheriting a static class do?

My answer: poor design choice. ;-)

This is an interesting debate focused on syntax impact. The core of the argument, in my view, is that a design decision led to sealed static classes. A focus on transparency of the static class's names appearing at the top level instead of hiding ('confusing') behind child names? One can image a language implementation that could access the base or the child directly, confusing.

A pseudo example, assuming static inheritance was defined in some way.

public static class MyStaticBase
{
    SomeType AttributeBase;
}

public static class MyStaticChild : MyStaticBase
{
    SomeType AttributeChild;
}

would lead to:

 // ...
 DoSomethingTo(MyStaticBase.AttributeBase);
// ...

which could (would?) impact the same storage as

// ...
DoSomethingTo(MyStaticChild.AttributeBase);
// ...

Very confusing!

But wait! How would the compiler deal with MyStaticBase and MyStaticChild having the same signature defined in both? If the child overrides than my above example would NOT change the same storage, maybe? This leads to even more confusion.

I believe there is a strong informational space justification for limited static inheritance. More on the limits shortly. This pseudocode shows the value:

public static class MyStaticBase<T>
{
   public static T Payload;
   public static void Load(StorageSpecs);
   public static void Save(StorageSpecs);
   public static SomeType AttributeBase
   public static SomeType MethodBase(){/*...*/};
}

Then you get:

public static class MyStaticChild : MyStaticBase<MyChildPlayloadType>
{
   public static SomeType AttributeChild;
   public static SomeType SomeChildMethod(){/*...*/};
   // No need to create the PlayLoad, Load(), and Save().
   // You, 'should' be prevented from creating them, more on this in a sec...
} 

Usage looks like:

// ...
MyStaticChild.Load(FileNamePath);
MyStaticChild.Save(FileNamePath);
doSomeThing(MyStaticChild.Payload.Attribute);
doSomething(MyStaticChild.AttributeBase);
doSomeThing(MyStaticChild.AttributeChild);
// ...

The person creating the static child does not need to think about the serialization process as long as they understand any limitations that might be placed on the platform's or environment's serialization engine.

Statics (singletons and other forms of 'globals') often come up around configuration storage. Static inheritance would allow this sort of responsibility allocation to be cleanly represented in the syntax to match a hierarchy of configurations. Though, as I showed, there is plenty of potential for massive ambiguity if basic static inheritance concepts are implemented.

I believe the right design choice would be to allow static inheritance with specific limitations:

  1. No override of anything. The child cannot replace the base attributes, fields, or methods,... Overloading should be ok, as long as there is a difference in signature allowing the compiler to sort out child vs base.
  2. Only allow generic static bases, you cannot inherit from a non-generic static base.

You could still change the same store via a generic reference MyStaticBase<ChildPayload>.SomeBaseField. But you would be discouraged since the generic type would have to be specified. While the child reference would be cleaner: MyStaticChild.SomeBaseField.

I am not a compiler writer so I am not sure if I am missing something about the difficulties of implementing these limitations in a compiler. That said, I am a strong believer that there is an informational space need for limited static inheritance and the basic answer is that you can't because of a poor (or over simple) design choice.

I run into the problem when trying to code an IComparer<T> implementation against a third-party library where T is an enum embedded in a class as in the following:

public class TheClass
{
    public enum EnumOfInterest
    {
    }
}

But because the enum is defined within a third-party library class, I can't write the comparer because the following gives a "cannot extends list" error:

public class MyComparer : IComparer<TheClass.EnumOfInterest>
{
}

I'm not even extending a static class -- I'm just implementing a comparer of a enum defined in a class.

Related