tags:

views:

561

answers:

9

I was looking at this blog post and had following questions:

  • Why do we need the new keyword, is it just to specify that a base class method is being hidden. I mean, why do we need it? If we don't use the override keyword, aren't we hiding the base class method?
  • Why is the default in C# to hide and not override? Why have the designers implemented it this way?
+3  A: 

In C# members are sealed by default meaning that you cannot override them (unless marked with the virtual or abstract keywords) and this for performance reasons. The new modifier is used to explicitly hide an inherited member.

Darin Dimitrov
But when do you really want to use the new modifier?
simendsjo
When you want to explicitly hide a member inherited from a base class. Hiding an inherited member means that the derived version of the member replaces the base-class version.
Darin Dimitrov
Added also abstract :)
Incognito
@Darin: But any methods using the base class will still call the base implementation, not the derived. This seems like a dangerous situation to me.
simendsjo
@simendsjo, @Darin Dimitrov: I also have a hard time thinking about a use case where the new keyword is really needed. It seems to me that there are always better ways. I also wonder whether hiding a base class implementation isn't a design flaw which easily leads to errors.
0xA3
A: 

You are correct that the new keyword explicitly hides a member from the base class so that callers end up using the member in your subclass rather than the superclass version. As that blog post also mentions, you can implicitly do this as well.

That's different than overriding a base class member; to do that the base class member must be marked as abstract or virtual. So not every member on a base class can be overridden. Suppose you're subclassing a class from someone else's assembly and you don't have access to, or don't want to, go back and retrofit that code to make the members virtual. Without the new keyword you would be stuck.

You can argue whether it's better to have the keyword and be explicit (my opinion) or to just do it implicitly.

Coding Gorilla
hiding the base class method is much different than overriding it. Callers will call the subclass method only when they are using the subclass. If the caller has an object declared as the base class, it will call the base class method.
tster
+8  A: 

If the method in the derived class is preceded with the new keyword, the method is defined as being independent of the method in the base class

However if you don't specify either new or overrides, the resulting output is the same as if you specified new, but you will get a compiler warning (as you may not be aware that you are hiding a method in the base class method, or indeed you may have wanted to override it, and merely forgot to include the keyword).

So it helps you to avoid mistakes and explicitly show what you want to do and it makes more readable code, so one can easily understand your code.

Incognito
+4  A: 

It is worth noting that the only effect of new in this context is to suppress a Warning. There is no change in semantics.

So one answer is: We need new to signal to the compiler that the hiding is intentional and to get rid of the warning.

The follow up question is: If you won't / can't override a method, why would you introduce another method with the same name? Because hiding is in essence a name-conflict. And you would of course avoid it in most cases.

The only good reason I can think of for intentional hiding is when a name is forced upon you by an interface.

Henk Holterman
+1  A: 

If overriding was default without specifying the override keyword, you could accidentally override some method of your base just due to the name equality.

.Net compiler strategy is to emit warnings if something could go wrong, just to be safe, so in this case if overriding was default, there would have to be a warning for each overriden method - something like 'warning: check if you really want to override'.

František Žiačik
A: 

My guess would mainly be due to the multiple interface inheritance. Using discreet interfaces it would be very possible that two distinct interfaces use the same method signature. Allowing the use of the new keyword would allow you to create these different implementations with one class, instead of having to create two distinct classes.

Updated ... Eric gave me an idea on how to improve this example.

public interface IAction1
{
    int DoWork();
}
public interface IAction2
{
    string DoWork();
}

public class MyBase : IAction1
{
    public int DoWork() { return 0; }
}
public class MyClass : MyBase, IAction2
{
    public new string DoWork() { return "Hi"; }
}

class Program
{
    static void Main(string[] args)
    {
        var myClass = new MyClass();
        var ret0 = myClass.DoWork(); //Hi
        var ret1 = ((IAction1)myClass).DoWork(); //0
        var ret2 = ((IAction2)myClass).DoWork(); //Hi
        var ret3 = ((MyBase)myClass).DoWork(); //0
        var ret4 = ((MyClass)myClass).DoWork(); //Hi
    }
}
Matthew Whited
When using multiple interfaces, you can name the interface methods explicitly to avoid collitions. I don't understand what you mean by "different implementation for one class" both have the same signature...
simendsjo
The `new` keyword allow you to also change the inheritance base for all of the children from that point.
Matthew Whited
+35  A: 

Good questions. Let me re-state them.

Why is it legal to hide a method with another method at all?

Let me answer that question with an example. You have an interface from CLR v1:

interface IEnumerable
{
    IEnumerator GetEnumerator();
}

Super. Now in CLR v2 you have generics and you think "man, if only we'd had generics in v1 I would have made this a generic interface. But I didn't. I should make something compatible with it now that is generic so that I get the benefits of generics without losing backwards compatibility with code that expects IEnumerable."

interface IEnumerable<T> : IEnumerable
{
    IEnumerator<T> .... uh oh

What are you going to call the GetEnumerator method of IEnumerable<T>? Remember, you want it to hide GetEnumerator on the non-generic base interface. You never want that thing to be called unless you're explicitly in a backwards-compat situation.

That alone justifies method hiding. For more thoughts on justifications of method hiding see my article on the subject.

Why does hiding without "new" cause a warning?

Because we want to bring it to your attention that you are hiding something and might be doing it accidentally. Remember, you might be hiding something accidentally because of an edit to the base class done by someone else, rather than by you editing your derived class.

Why is hiding without "new" a warning rather than an error?

Same reason. You might be hiding something accidentally because you've just picked up a new version of a base class. This happens all the time. FooCorp makes a base class B. BarCorp makes a derived class D with a method Bar, because their customers like that method. FooCorp sees that and says hey, that's a good idea, we can put that functionality on the base class. They do so and ship a new version of Foo.DLL, and when BarCorp picks up the new version, it would be nice if they were told that their method now hides the base class method.

We want that situation to be a warning and not an error because making it an error means that this is another form of the brittle base class problem. C# has been carefully designed so that when someone makes a change to a base class, the effects on code that uses a derived class are minimized.

Why is hiding and not overriding the default?

Because virtual override is dangerous. Virtual override allows derived classes to change the behaviour of code that was compiled to use base classes. Doing something dangerous like making an override should be something you do consciously and deliberately, not by accident.

Eric Lippert
Thanks a lot! Great explanation!
0xA3
FWIW, I disagree that “[t]hat alone justifies method hiding.” Sometimes it’s better to break backwards compatibility. Python 3 has shown that this actually works without destroying too much work. It’s important to note that “backwards compatibility at all cost” is not the only reasonable option. And this reason carries over to the other point: changing a base class will *always* be brittle. Breaking a dependent build might actually be preferable. (But +1 for answering the question from my comment below the actual question.)
Konrad Rudolph
@Konrad: I agree backward compability can hurt. Mono has decided to drop support for 1.1 in future releases.
simendsjo
@Konrad: Breaking backward compatibility with your language is very different than making it easy for people using your language to break backwards compatibility with their own code. Eric's example is the 2nd case. And the person writing that code has made a decision that he wants backwards compatibility. The language should support that decision if possible.
Brian
God answer, Eric. However, there is a more specific reason why overriding by default is bad. If a base class Base introduces a new method Duck() (which returns a duck object) that _just happens_ to have the same signature as your existing method Duck() (which makes Mario duck) in a derived class Derived (i.e. no communication between you and the writer of Base), you do _not_ want clients of both classes to make Mario duck when they just want a Duck.
apollodude217
In summary, it mostly has to do with changing base classes and interfaces.
apollodude217
@Brian: Python 3 shows that the two cases come down to the same. I agree that there may be differences but I don’t agree that they are substantial. In both cases, the users of the language are forced to take steps to ensure that their code still works.
Konrad Rudolph
A: 

As noted, method/property hiding makes it possible to change things about a method or property which could not be readily changed otherwise. One situation where this can be useful is allowing an inherited class to have read-write properties which are read-only in the base class. For example, suppose a base class has a bunch of read-only properties called Value1-Value40 (of course, a real class would use better names). A sealed descendant of this class has a constructor that takes an object of the base class and copies the values from there; the class does not allow them to be changed after that. A different, inheritable, descendant declare a read-write properties called Value1-Value40 which, when read, behaves the same as the base class versions but, when written, allows the values to be written. The net effect will be that code which wants an instance of the base class that it knows will never change can create a new object of the read-only class, which can copy data from a passed-in object without having to worry whether that object is read-only or read-write.

One annoyance with this approach--perhaps someone can help me out--is that I don't know of a way to both shadow and override a particular property within the same class. Do any of the CLR languages allow that (I use vb 2005)? It would be useful if the base class object and its properties could be abstract, but that would require an intermediate class to override the Value1 to Value40 properties before a descendant class could shadow them.

supercat
A: 

The designer of C# explains why here:

http://www.artima.com/intv/nonvirtual.html

apollodude217
[Eric Lippert](http://stackoverflow.com/users/88656/eric-lippert) described it [here](http://stackoverflow.com/questions/3117838/why-do-we-need-the-new-keyword-and-why-is-the-default-behavior-to-hide-and-not-ov/3118480#3118480)
John Saunders