C# static member "inheritance" - why does this exist at all?

C#InheritanceStaticLanguage Design

C# Problem Overview


In C#, a superclass's static members are "inherited" into the subclasses scope. For instance:

class A { public static int M() { return 1; } }
class B : A {}
class C : A { public new static int M() { return 2; } }
[...]
A.M(); //returns 1
B.M(); //returns 1 - this is equivalent to A.M()
C.M(); //returns 2 - this is not equivalent to A.M()

Now, you can't inherit static classes, and the only place I can imagine that static inheritance might matter ignores it entirely: although you can make a generic constraint that requires a type parameter T to be a subclass of A, you still cannot call T.M() (which probably simplifies things for the VM), let alone write a different M implementation in a subclass and use that.

So, the "inheritance" of static members merely looks like namespace pollution; even if you explicitly qualify the name (i.e. B.M) A's version is still resolved.

Edit compare with namespaces:

namespace N1{  class X();   }
namespace N1.N2 {  class X();   }
namespace N1.N2.N3 { [...] }

Within N1.N2.N3 It makes sense that if I use X without qualification it refers to N1.N2.X. But if I explicitly refer to N1.N2.N3.X - and no such class exists - I don't expect it to find N2's version; and indeed to compiler reports an error if you try this. By contrast, if I explicitly refer to B.M(), why doesn't the compiler report an error? After all, there's no "M" method in "B"...

What purpose does this inheritance have? Can this feature be used constructively somehow?

C# Solutions


Solution 1 - C#

> So, the "inheritance" of static > members merely looks like namespace > pollution

That's right, except that one guy's pollution is another guy's added spicy flavouring.

I think Martin Fowler, in his work on DSLs, has suggested using inheritance in this way to allow convenient access to static methods, allowing those methods to be used without class name qualification. So the calling code has to be in a class that inherits the class in which the methods are defined. (I think it's a rotten idea.)

In my opinion, static members should not be mixed into a class with a non-static purpose, and the issue you raise here is part of the reason why it's important not to mix them.

Hiding private static mutable data inside the implementation of an otherwise "instancey" class is particularly horrible. But then there are static methods, which are even worse mixers. Here's a typical use of static methods mixed into a class:

public class Thing
{
    // typical per-instance stuff
    int _member1;
    protected virtual void Foo() { ... }
    public void Bar() { ... }

    // factory method
    public static Thing Make()
    {
        return new Thing();
    }
}

It's the static factory method pattern. It's pointless most of the time, but even worse is that now we have this:

public class AnotherThing : Thing { }

This now has a static Make method which returns a Thing, not a AnotherThing.

This kind of mismatch strongly implies that anything with static methods should be sealed. Static members fail to integrate well with inheritance. It makes no sense to have them heritable. So I keep static things in separate static classes, and I gripe about redundantly having to declare every member static when I've already said that the class is static.

But it's just one of those too-late-now things. All real, working languages (and libraries, and products) have a few of them. C# has remarkably few.

Solution 2 - C#

I rather have access to all my based static members in derived classes. Otherwise i would need to know exactly where the static member was defined and call it explicitly.

When using Intellisense you can automatically know every static member available to that kind of class.

Of course, they are not inherited, it's just a shortcut

Solution 3 - C#

That's how it works, would probably just be a stupid answer in most cases. But in this case, it is how it works; since you derive from A you say that you are A + the extra features you add.

Therefore you need to be able to access the same variables that you would through an instance of A.

However, inheriting a static class makes no sense while access to the static members / fields / methods does.

An example of this is the following:

internal class BaseUser
{
    public static string DefaultUserPool { get; set; }
}
internal class User : BaseUser
{
    public int Id { get; set; }
    public string Name { get; set; }
    public User Parent { get; set; }
}

Where the test looks like this:

User.DefaultUserPool = "Test";
BaseUser.DefaultUserPool = "Second Test";

Console.WriteLine(User.DefaultUserPool);
Console.WriteLine(BaseUser.DefaultUserPool);

Both of the WriteLines outputs "Second Test", this is because both BaseUser and User should use DefaultUserPool, by design. And overriding static implemented methods wouldn't make mucn sense since it's just an accessor in the child-class.

There can be only one. Overriding it would mean that there's a new implementation for that sub-class, which would kill the term "static".

Solution 4 - C#

Actually, as I understand it, this is just a shortcut provided by the compiler. Syntax sugar. B.M() will just compile to A.M() since B does not have a static M() and A does. It's for easier writing, nothing else. There is no "static inheritance".

Added: And the requirement for new when "redefining" is just so that you don't accidentally shoot yourself in the foot.

Solution 5 - C#

I think it's for accessing protected static members of the base class.

class Base
{
    protected static void Helper(string s)
	{
	   Console.WriteLine(s);
	}
}

class Subclass : Base
{
   public void Run()
	{
	   Helper("From the subclass");
	}
}

Solution 6 - C#

So... What's the alternative?

The question mentions...

> why doesn't the compiler report an error? After all, there's no "M" method in "B"...

But there is a derived "M" method in "B" class.

If the compiler did not present the programmer a unified virtual table for base cases, then the programmer would have to go hunting through base types to find static methods. This would break polymorphism.

Wikipedia... > Subtype polymorphism, almost universally called just polymorphism in the context of object-oriented programming, is the ability of one type, A, to appear as and be used like another type, B.... > >In strongly typed languages, polymorphism usually means that type A somehow derives from type B, or type C implements an interface that represents type B.

Solution 7 - C#

I always see it a means of preventing any form of polymorphism by the inheriting class on those items that you wish to retain the same function for all child classes.

ignore the above for some reason I was thinking of sealed instead of static

I suppose that you'd use static member variables and functions in order to ensure that any data or functionallity is not dependent on the a class instance as it would be instantiated only the once.

An example of use would be say a counter value that would keep a live count of all instances of a superclass's subclasses (each subclass increments the static count value on construction). This count value would be available and equal for all instances of the subclass.

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionEamon NerbonneView Question on Stackoverflow
Solution 1 - C#Daniel EarwickerView Answer on Stackoverflow
Solution 2 - C#Luis FilipeView Answer on Stackoverflow
Solution 3 - C#Filip EkbergView Answer on Stackoverflow
Solution 4 - C#Vilx-View Answer on Stackoverflow
Solution 5 - C#TrueWillView Answer on Stackoverflow
Solution 6 - C#kervinView Answer on Stackoverflow
Solution 7 - C#ChrisBDView Answer on Stackoverflow