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.
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.
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.
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
.
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.