views:

161

answers:

5

I'm new to c# so bare with me. But here's my situation.

interface Icontainer{
 string name();
}

abstract class fuzzyContainer : Icontainer{
  string name(){
   return "Fuzzy Container";
  }
}

class specialContainer: fuzzyContainer{
  string name(){
   return base.name() + " Special Container";
  }
}


Icontainer cont = new SpecialContainer();
cont.name(); // I expected "Fuzzy Container Special Container" as the output.

When I run my code as described above the output is simply "Fuzzy Container". What am i missing here? Is there a better way to get the desired results?

+17  A: 

If you make name() virtual and then override in specialContainer, you will get the expected behavior.

public interface Icontainer
{
    string name();
}

public abstract class fuzzyContainer : Icontainer
{
    public virtual string name()
    {
        return "Fuzzy Container";
    }
}

public class specialContainer : fuzzyContainer
{
    public override string name()
    {
        return base.name() + " Special Container";
    }
}
Matt Greer
+3  A: 

This is because you are hiding the method and not overriding it. Without making the base method virtual it isn't possible to override it, but you can "hide" it by creating a method of the same name.

If you had:

SpecialContainer cont = new SpecialContainer();
cont.name();

Then you will also get the output you expected.

Matt's answer also works and may be preferable if you can edit the base class to make the method virtual. By default methods are not overridable unless explicitly marked as such with the virtual keyword

Davy8
A: 

The 'name' method in that class is not an override of fuzzyContainer's Name method. So when you cast the specialContainer object as an IContainer, it only has the base class' Name method to invoke.

Tejs
+3  A: 

You need to declare the name-method virtual and the override it in the derived class.

I also took the liberty of "fixing" your code with the most common naming conventions.

abstract class FuzzyContainer : IContainer{
  protected virtual string GetName(){
   return "Fuzzy Container";
  }
}

class SpecialContainer: FuzzyContainer{
  override string GetName(){
   return base.GetName() + " Special Container";
  }
}
CodingInsomnia
+6  A: 

First off, it is helpful when you have questions that you post code that actually compiles. It is difficult to analyze a problem when it is full of missing modifiers and typos; it is hard to know whether the problem is the typo or not.

Once we do the work to fix up your program so that it actually compiles, the compiler emits a warning that tells you that the overloading looks wrong. Since your question is "why is the overloading wrong?" it would probably be a good idea to read the compiler warning that we emitted precisely so that you can analyze this problem.

The problem is that the derived class contains a new method called "name", not an override of the existing method. That's what the warning is trying to tell you.

There are two ways to fix this problem, depending on whether you intended the method to be "new" or "override". If you intended the method to be "override" then make the base implementation virtual and the derived implementation override.

If you intended the method to be "new" and you still want the new method to replace the binding to the interface implementation then use interface reimplementation:

class SpecialContainer: FuzzyContainer, IContainer 
{
  public new string Name()
  { 
    return base.Name() + " Special Container"; 
  } 
} 

Notice the "new" and the fact that we have re-stated that this class implements IContainer. This tells the compiler "disregard the bindings to methods of IContainer deduced from the base class and start over."

Eric Lippert
Are there any truly compelling situations where you would use `new`? The only time I find I am using `new` is when I am attempting to force a design I shouldn't be.
Matt Greer
@Matt: IEnumerable<T> extends IEnumerable. Both have a method called GetEnumerator that takes no arguments. You have three choices. (1) don't make the generic version type compatible with the nongeneric version; break the extension relationship. (2) come up with a different name for GetEnumerator in the derived interface. Or (3) make the derived version's GetEnumerator a "new" method. Which do you think is least awful of these three bad choices? I would go for (3).
Eric Lippert