Omer van Kloeten's .NET Zen

Programming is life, the rest is mere details

News

Omer van Kloeten's Facebook profile

Omer has been professionally developing applications over the past 8 years, both at the IDF’s IT corps and later at the Sela Technology Center, but has had the programming bug ever since he can remember himself.
As a senior developer at NuConomy, a leading web analytics and advertising startup, he leads a wide range of technologies for its flagship products.

Get Firefox


powered by Dapper 

.NET Resources

Articles :: CodeDom

Articles :: nGineer

Culture

Projects

Type Inheritance?

I've come across something I find disturbing in C#.
Let's begin with an example:

#region Case 1
public class MyBaseClass
{
	public static void MyStaticMethod()
	{
		// Work Some Magic
	}
}

public class MyDerivedClass : MyBaseClass
{
	public static void MyStaticMethod() // I will get a warning for not using 'new'
	{
		// Work Some Other Magic
	}
}
#endregion

#region Case 2
public class MyOtherDerivedClass : MyBaseClass
{
}

public class SomeOtherClass
{
	public int Main(string[] args)
	{
		MyOtherDerivedClass.MyStaticMethod(); // This would pass without a hitch!
	}
}
#endregion

I have looked through the specs and it seems this is actually correct behaviour.
Why do my static members get inherited to the derived type? Does anyone have a good reason for this or knows the fact of why this came to be?

[ Update: Paul Bartlett and Josh Flanagan note that this behvaiour is C# specific and that when calling a 'derived' static member on a derived type, the end-result IL will call the base class. That's just another reason why I think this doesn't make sense. ]


Tip: View this page in IE and try clicking on the region directives. I'm now trying to get the script to work with Mozilla as well...
[Update: Code now works for Mozilla users (that's what happens when you use IE's non-standard implicit document.all object.]

Comments

TrackBack said:

# July 6, 2004 8:47 AM

Ido Samuelson said:

Think about it. If you have static memebers in your base class you must have access to them in your derived classes. Furthermore, if you initialize your static members in a static constructor then you get me point why a derived class should inheirt also the other static types.
# July 6, 2004 3:17 PM

Michael Russell said:

Would you rather cast your items back to Object, then call .ToString on them, or would you be content with doing Foo.ToString without knowing the type of Foo?

By allowing these static members to trickle down, it can make code easier to write.
# July 6, 2004 3:18 PM

Ido Samuelson said:

You are so bored...well your Pentium 3 is enough power for javascripting ;)
# July 6, 2004 3:28 PM

Omer van Kloeten said:

Ido-

Why should I get access to the derived members? It's not as if I have anything that affects any instances in there. If I initialize the static members in the static constructor in the base class, it would be called anyway, since an instance of the deriving type is created, causing an instance of the base type to be 'created', causing the static constructor to run.
And no, I'm not THAT bored. You'll see soon enough. ;)

Michael-

There's a difference between inheritance of instance members and inheritance of static members. I can't argue that using myInstance.ToString is better than doing ((object)(myInstance.ToString)).
However, static members are members of a type. There's no overriding on a virtual static member. Why should there be 'new'?
Object.ReferenceEquals(a, b) is alright, but why should I be able to call MyType.ReferenceEquals(a, b)? What meaning does that have when I haven't implemented a method of that name in the MyType class?
# July 6, 2004 3:31 PM

Josh Flanagan said:

I agree that it doesn't make sense. I'm curious to hear why it is implemented as is. Have you submitted it to the C# FAQ blog?
# July 6, 2004 3:36 PM

Paul Bartlett said:

I was looking at this a while back (see http://blogs.geekdojo.net/pdbartlett/archive/2004/04/06/1578.aspx). As the comments show, this is a C#-ism rather than CLR behaviour. As to whether I agree with it, that's a question for another day...
# July 7, 2004 3:25 AM

Scott Allen said:

I guess I don't understand why there is an objection to the behavior. MyOtherDerivedClass inherits MyBaseClass. It "is a" MyBaseClass. I want to be able to work with MyOtherDerivedClass as if it were MyBaseClass, including calling the static methods of MyBaseClass.

What if MyBaseClass included a static integer field? All instances of MyBaseClass will share the field. I'd expect all instances of MyOtherDerivedClass to share the same field. I inherited the class, I don't want the field to simply "dissapear" from the inheritance chain just because it is shared.
# July 7, 2004 12:59 PM

Omer van Kloeten said:

Scott,

The question is not what is more comfortable, but what is more correct.

I usually use static members as stateless services for a type. Using those same members on a derived type might not have the same effect as I have intended.

But that's just me. I don't see what benefits I have by using MyType.ReferenceEquals instead of Object.ReferenceEquals (when with the latter it is clear that it applies to all objects and with the former it just seems this applies to only MyType, when it doesn't).

I'm just trying to observe the supports on which the house was built. They might be shaky and we just don't know it.
# July 7, 2004 2:01 PM

Josh Flanagan said:

Your original post states that you found this behavior in "C# and other .NET languages". What other languages did you find it in? Because according to a comment in the post that Paul links to, this behavior is NOT supported in the runtime. It is enabled by the C# compiler.
When you write
MyOtherDerivedClass.MyStaticMethod()
in C#, the compiler emits an MSIL call to:
MyBaseClass.MyStaticMethod()
# July 7, 2004 4:42 PM
Leave a Comment

(required) 

(required) 

(optional)

(required)