paulio
paulio

Reputation: 393

C# ToString inheritance

I have a problem (it's my fault, I just can't spot what I'm doing wrong) where "ToString" isn't calling the correct method...

public class ClassA
{
   public override ToString()
   {
      return "Hello, I'm class A.";
   }
}

public class ClassB : ClassA
{
   public override ToString()
   {
       return "Hello, I'm class B.";
   }
}

ClassB myClassB = new ClassB();
List<ClassA> myClassAList = new List<ClassA>();

myClassAList.Add((ClassA) myClassB);
ClassA tempClassA = myClassAList[0];
Console.WriteLine(tempClassA.ToString());

I'm getting the "ToString" from "ClassB" and not "ClassA" what am I doing wrong?

Upvotes: 3

Views: 5116

Answers (4)

Quintin Robinson
Quintin Robinson

Reputation: 82355

You are overriding ToString in ClassB instead of hiding it from the original which will cause the overridden method to take precedence. What you could do is..

public class ClassA
{
    public override string ToString()
    {
        return "Hello, I'm class A.";
    }
}

public class ClassB : ClassA
{
    public new string ToString()
    {
        return "Hello, I'm class B.";
    }
}

...

List<ClassA> theList = new List<ClassA>
{
    (ClassA)new ClassB(),
    (ClassA)new ClassB()
};

ClassA a = theList[0];
Console.WriteLine(a.ToString());

// OR... 

Console.WriteLine(new ClassA().ToString());  // I'm Class A
Console.WriteLine(new ClassB().ToString());  // I'm Class B
Console.WriteLine(((ClassA)new ClassB()).ToString()); // I'm Class A

Upvotes: 4

driis
driis

Reputation: 164331

You are getting the correct results. You add an instance of ClassB to your list; even though you treat it as a ClassA. Therefore, when you call the virtual ToString method, it will result in a call to ClassB's ToString; because that is the actual kind of object you are working with.

Upvotes: 0

Srdjan Jovcic
Srdjan Jovcic

Reputation: 773

You are not doing anything wrong -- this is how polymorphism virtual methods work. When you put ClassB into collection of ClassA references, it is still ClassB object. Invoking .ToString() will always find ClassB.ToString() if the object is indeed of ClassB.

Upvotes: 6

Lasse V. Karlsen
Lasse V. Karlsen

Reputation: 391506

ToString is a virtual method, it doesn't matter what the type of your variable is, it matters what the type of the actual object is.

If the method wasn't virtual, a call would go to the method the compiler would know about, which would be the ClassA ToString method.

Virtual methods are implemented through a lookup table, bound to the object type. Since the object you end up with in variable "tempClassA" is really an object of type ClassB, the lookup table for ClassB is used, and thus the ToString method for that class is used.

Upvotes: 0

Related Questions