Why does my Static method hide my instance method?

Should the following code give a warning?

class Foo { public void Do() { /*...*/ } /*...*/ }
class Bar : Foo { public static void Do() { /*...*/ } /*...*/ }

It gives:

“Warning CS0108: ‘Bar.Do()’ hides inherited member ‘Foo.Do()’. Use the new keyword if hiding was intended.”

If I make a change to the code:

class Foo { public static void Do() { /*...*/ } /*...*/ }
class Bar : Foo { public void Do() { /*...*/ } /*...*/ }

I get the same warning.

If I make the following change, however, the warning goes away.

class Foo { public void Do() { /*...*/ } /*...*/ }
class Bar : Foo { new public static void Do() { /*...*/ } /*...*/ }

Let me make a further change:

class Foo { public void Do() { /*...*/ } /*...*/ }
class Bar : Foo {
new public static void Do()
{ new Bar().Do();/*...*/ } /*...*/
}

This does not compile:

“Error CS0176: Member ‘Bar.Do()’ cannot be accessed with an instance reference; qualify it with a type name instead.”

So, I lose access to my inherited method via an instance reference from a static method!

What would be the logic behind it? Or did I make a typo somewhere?

I came across this when I was trying to define a static method ‘Show’ for my form derived from ‘Form’.

Best Answer:

Where do you think the bug is? The fact that there is a warning is absolutely right. From the C# 3.0 spec, section 10.3.4:

A class-member-declaration is
permitted to declare a member with the
same name or signature as an inherited
member. When this occurs, the derived
class member is said to hide the base
class member. Hiding an inherited
member is not considered an error, but
it does cause the compiler to issue a
warning. To suppress the warning, the
declaration of the derived class
member can include a new modifier to
indicate that the derived member is
intended to hide the base member.

The fact that your method invocation fails is subtler, but it’s basically because the member lookup algorithm picks the static method, and then this part of section 7.5.5.1 is used:

Final validation of the chosen best
method is performed:

The method is
validated in the context of the method
group: If the best method is a static
method, the method group must have
resulted from a simple-name or a
member-access through a type. If the
best method is an instance method, the
method group must have resulted from a
simple-name, a member-access through a
variable or value, or a base-access.
If neither of these requirements is
true, a compile-time error occurs.


Other Answer 1:

No, that makes perfect sense. This works as expected:

using System;
using System.Collections.Generic;

class Foo { public void Do() { /*...*/ } /*...*/ }
class Bar : Foo {
new public static void Do()
{ ((Foo)new Bar()).Do();/*...*/ } /*...*/
}

That’s because the compiler assumes that you have a Bar type, and then finds the static member. By casting it to Foo (which comes for free btw.) you make it look in the metdadata for Foo() and all is fine.


Other Answer 2:

Try this:

        new public static void Do()
{
((Foo)new Bar()).Do();
}


Other Answer 3:

you should be able to call it by doing calling base.Do() rather than Bar().Do()


Other Answer 4:

In your final code sample, the new keyword on the declaration of Bar.Do() means that you intended to hide Foo.Do().