Click here to Skip to main content
15,880,503 members
Please Sign up or sign in to vote.
1.00/5 (1 vote)
See more:
Lets get this code as example:
C#
public class Shape
{
    // A few example members
    public int X { get; private set; }
    public int Y { get; private set; }
    public int Height { get; set; }
    public int Width { get; set; }
   
    // Virtual method
    public virtual void Draw()
    {
        Console.WriteLine("Performing base class drawing tasks");
    }
}

class Circle : Shape
{
    public override void Draw()
    {
        // Code to draw a circle...
        Console.WriteLine("Drawing a circle");
        base.Draw();
    }
}
class Rectangle : Shape
{
    public override void Draw()
    {
        // Code to draw a rectangle...
        Console.WriteLine("Drawing a rectangle");
        base.Draw();
    }
}
class Triangle : Shape
{
    public override void Draw()
    {
        // Code to draw a triangle...
        Console.WriteLine("Drawing a triangle");
        base.Draw();
    }
}



So when I write this code:
C#
class Program
{
    static void Main()
    {
        Circle c = new Circle();
        Shape s = (Shape)c;
    }
}


How its working ? Shape s reference is now pointing to c treated as a Shape type in the memory or ? If I want to cast c to Shape why i cant just write one line code like this
C#
class Program
{
    static void Main()
    {
        Circle c = new Circle();
        (Shape)c;
    }
}


What I have tried:

Watched video tutorials and read the Microsoft Docs but still very confused.
Posted
Updated 2-Jul-17 22:47pm

Quote:
Circle c = new Circle();
Shape s = (Shape)c;
You don't need to cast (because a Circle is a Shape), try:
Circle c = new Circle();
Shape s = c;



Quote:
(Shape)c;
That's redundant, because, again, a Circle is a Shape.


Quote:
Watched video tutorials and read the Microsoft Docs but still very confused.
Try reading a book on OOP.
 
Share this answer
 
Comments
Maciej Los 3-Jul-17 4:39am    
5ed!
CPallini 3-Jul-17 5:09am    
Thank you!
The_Unknown_Member 3-Jul-17 4:44am    
Noooo. I wanted to ask how the cast is working in this example:
class Program
{
static void Main()
{
Shape s = new Circle();
Circle c = (Circle)s;
c.Draw();
}
}

Im aware of what is Polymorphism and how it works but I cant understand how the cast is working in this example. Also sorry for the bad explaination hope you got the point of what I mean.
First of all you have to understand reference types in general. You have a Circle object somewhere in memory and you have two variables pointing to it, or referencing it; one is "c" and one is "s". If you update a variable via "c" then "s" will see the same as there is only one actual object that both are looking at.

Circle c = new Circle();
Shape s = (Shape)c;

c.Height = 123;

int h = s.Height; // h is 123

s.Height = 456;

h = c.Height; // h is 456


Think about your object like a set of Russian dolls with dolls inside each other. So you have a doll called Circle, and inside that a doll called Shape, and inside that a doll called Object. That is your inheritance tree (everything inherits from Object ultimately). There is only one object of nested dolls, but "c" is holding the outer Circle doll and "s" is holding the Shape doll inside it. So "c" has accesses to the Circle doll and everything inside it so it can see properties on Circle, Shape and Object. However as "s" is holding the inner Shape doll it can only see properties on Shape and the Object doll inside it. However if "s" updates some property of that Shape doll then "c" sees that also.
 
Share this answer
 
Comments
Richard MacCutchan 3-Jul-17 4:59am    
Excellent analogy.
Maciej Los 3-Jul-17 5:04am    
5ed!
The_Unknown_Member 3-Jul-17 6:51am    
Excellent. Just in 7 sentences you explained very well what is inheritance and polymorphism with a real world example. Thanks you a lot! Btw also these Russian dolls are called "Matryoshka" if you didn't know.
[no name] 5-Jul-17 3:00am    
One of Best Explanations i have read so far in this week +5
You can just type this:
C#
Circle c = new Circle();
(Shape)c;
And it's valid C# - it just doesn't do anything useful because you discard the value you cast.

When you do this:
C#
Circle c = new Circle();
Shape s = c;
You create two variables c and s, and you make them both refer to the same object. It's like cars: "this car" and "my car" can both reference the same vehicle in different ways.

When you create a class derived from a base class as you do with Circle and Shape, a Shape variable can hold a reference to any Shape object instance, including all objects which are of a class derived from Shape because the action of deriving a class is saying "this new class is the base class, but it can do more as well".
And as a result, you can use the properties, methods, and events from the base class on any derived class instance. Going back to cars for a moment, If there is a base Car class, then you derive a manufacturer from that: Mercedes derives from Car, as do Ford, Ferrari, and Audi. That means that every vehicle Mercedes makes is a Car, but does not mean that every Ford is a Ferrari because they share a common base. A variable which contains a Car (such as "this car" or "that car", "my car" or "your car" can do anything that is common to all cars: CountTheWheels (always returns 4), GetTheColour (because all vehicles have a colour), Drive (because all vehicles drive in a very similar way). But you can't take a Mercedes variable and execute a Ford method on it: ServiceMyFord doesn;t exist for a my car, because Mr Ford didn't make it, Mr Benz did, and the service requirements are different.

The system uses the actual instance to work out what type it actually is and call the right method.

For example, Car may have a default DriveTo method, which Mercedes overrides, but which Ford overrides differently - When you call DriveTo on a Car variable the system looks at the contents, finds it's a Ford and calls the Ford version of the method automatically.

Does that make sense?
 
Share this answer
 
Comments
The_Unknown_Member 3-Jul-17 7:19am    
Yeah It makes sense. You gave me a real world example and very thanks for that. But this wasn't what I asked. I am awful at explaining things to the people and I hate myself for that. Just look at this code and I think you will understand what I ask:

using System;
using System.Collections.Generic;

class Program
{
static void Main()
{
List<Person> people = new List<Person>();
people.Add(new Employee());
people.Add(new Student());

Person p = new Employee();
Employee e = p as Employee; // I want to ask what is happening in this line code when I do the cast in the assignment part
}
}

class Person
{
public string Name { get; set; }
public int Age { get; set; }
}

class Employee : Person
{
public string ID { get; set; }

public void IntroduceSelf()
{
Console.WriteLine("Hello my name is {0} and my ID is {1}", Name, ID);
}
}

class Student : Person
{
public int GradeLevel { get; set; }
}
OriginalGriff 3-Jul-17 8:43am    
That's a bit more complicated that your original example: Because Employee is derived from Person, not every instance of a Person is an Employee - any more than every Vehicle is a Car; some of them are a Bus, or a Lorry, or a Motorcycle.
So when you use "as":

Employee e = p as Employee;

The value in e can be one of two different things:
1) It can be an Employee instance, if p held an employee.
Or
2) It can be null, if p was null, or p contained a Person who was not an employee:

Student s = new Student();
Person p = s;
Employee e = p as Employee;

In this case, the instance involved is a Student - which means it's a Person - so it's fine to store it in a Person variable.
But a Student isn't an Employee, they just share a "common ancestor" - Person - so the "as" operator returns null because a Student cannot be converted to an Employee.

Think about it: it's the only sensible thing to do. If you stored a Student in an Employee variable, you could try to call "PayWages" on the Student - and Student doesn't define a PayWages method because nobody wants to pay students anything! :laugh:
Back to car terms, and both a Ford and Ferrari are instances of a Car - but you can't change a Ford Ka into a Ferrari just by swapping the badges! (And people will laugh at you a lot if you do that.)
The_Unknown_Member 3-Jul-17 12:00pm    
I think I understood it:

Person p = new Employee();
Employee e = p as Employee;

So in the first line I am making Person reference with name "p" and making this reference pointing to an instance of the object Employee. But since the reference variable is of type Person I am able to see only the specific things for the Person class. In simple words: I am watching through the eyes of Person. And in the second line I am making an Employee reference variable with name "e" and making this "e" variable pointing to the same address to which "p" is pointing to but treated as an Employee.

Did I understand it in the right way ?
OriginalGriff 3-Jul-17 12:16pm    
Pretty much, yes!
The only difference is that even if your variable p is a Person-referencing-an-Employee, the system will use Employee methods if they override Person ones. In other words, if your Person class has a method DoIt:

public virtual void DoIt() { Console.WriteLine("DoIt Person!"); }

And your Employee class overrides that:

public override void DoIt() { Console.WriteLine("DoIt Employee"); }

Then this code:

Person p = new Employee();
p.DoIt();

Will still call the Employee version and print:

DoIt Employee

Because the system knows that the instance is of a derived class and has a more relevant method, so it uses that.

The_Unknown_Member 3-Jul-17 13:31pm    
Yeah I know that. Also its calling the constructor of Employee.

This content, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)



CodeProject, 20 Bay Street, 11th Floor Toronto, Ontario, Canada M5J 2N8 +1 (416) 849-8900