How Upcasting preserve derived classes's Properties?

654 views Asked by At
        static void Main(string[] args)
        {
            Student student = new Student()
            {
                ID = 12,
                Name = "Manu",
                LastName = "Shekar"
            };

            Iregister x = student;
            Student newstudent = x as Student;

           //Console.WriteLine(x.LastName); //Uncommenting this shows compilation error
            Console.WriteLine(newstudent.LastName); //This Show "Shekar"
            Console.ReadKey();

        }


    class Student : Iregister
    {
        public int ID { get; set; }
        public string Name { get; set; }
        public String LastName { get; set; }

    }
    interface Iregister
    {
        int ID { get; set; }
        String Name { get; set; }


    }

I wonder how the newstudent.LastName gets the correct value since it is casted from Iregister which doesn't have LastName property? How the value "Shekar" is passed from student.LastName to newstudent.LastName. Did x stores it somewhere in between? Pardon me if i miss something basics.

4

There are 4 answers

0
Damien_The_Unbeliever On BEST ANSWER

You create a single object, and assign a reference to it in the variable student.

You then create a second reference to the same object and assign that to x. Both x and student are referring to the same object, but the type of the x variable means that only the members defined on IRegister are available.

You then create a third reference to the same object and assign that to newstudent. Since newstudent is of type Student, you can access all of the member of Student from that reference.

Not that the variables just store references. It's the object that stores its own actual data, and that object remained unchanged throughout the process.

0
Ousmane D. On

I wonder how the newstudent.LastName gets the correct value since it is casted from Iregister which doesn't have LastName property?

The truth is that x is a type Iregister but it's pointing to a Student object hence once casted you're able to access the Student fields.

6
Kapol On

When using x directly, the compiler allows you to choose only the members defined on IRegister type, because x is of that type. Once you cast x to Student, the compiler allows you to use any member of Student, since the newstudent variable is of type Student.

0
Flater On

How Interface stores inherited class's Property

Interfaces do not store values. They only ensure the availability of certain properties and methods in the classes that implement the interface.

I wonder how the newstudent.LastName gets the correct value since it is casted from Iregister which doesn't have LastName property?

Downcasting an object does not change the object's type, it only changes the type of the variable that you're using.

public interface IMyInterface
{
    String Name { get; }
}

public class BaseType : IMyInterface
{
    public virtual String Name
    {
        get { return "Base Name"; }
    }
}

public class DerivedType : BaseType
{
    public override String Name
    {
        get { return "Derived Name"; }
    }
}

I then tested the following commands in the C# Interactive window:

var derived = new DerivedType();

IMyInterface derivedAsInterface = derived;
BaseType derivedAsBaseType = derived;

derived.Name                //returns "Derived Name"
derivedAsInterface.Name     //returns "Derived Name"
derivedAsBaseType.Name      //returns "Derived Name"

As you can see, whenever you ask for the Name property, the object still behaves as a DerivedType, because that is what the object is.

This is because classes are inherently reference types. This does work differently for value types (e.g. float and int), but that has to do with the inherent differences between value and reference types.
If you want to know why, read up on the difference between value and reference types in C#


If you think about it, your assumption does not make sense. In my code example, I have three separate variables: derived, derivedAsInterface, derivedAsBaseType. These all point to the same object in memory.

This logically means that the same object must be compatible with all three variables, otherwise it would be impossible to use all these variables when you want to.

  • If the object was changed into an object of type IMyInterface, then my variables derivedAsBaseType and derived would no longer function correctly.
  • If the object was changed into an object of type BaseType, then my variable derived would no longer function correctly.
  • The only remaining explanation is that my object has always kept its original type (DerivedType), since that is the only way how it can maintain compatibility with all three variables.

If you do not understand why they refer to the same object in memory, you should read up on the difference between value and reference types in C#. This topic is much too broad for an answer on StackOverflow.