downcasting in C#
Page 1 of 1
CraweN




Posts: 719
Location: Upside down in chair
PostPosted: Sat, 26th Feb 2011 23:51    Post subject: downcasting in C#
Hey people.
Playing around with abstract classes and polymorphisme. Made a small test program, but I'm having a small problem with understanding the concept of "downcasting".
I'll show the code first.

Code:
class Program
    {
        static void Main(string[] args)
        {
            BaseShape myShape;
            myShape = new TriangleShape(3.0, 10.0, 10.0);
            myShape.CalculateArea();
            myShape = new RectangleShape(3.0, 10.0, 10.0);
            myShape.CalculateArea();
        }
    }

abstract class BaseShape
    {
        private double area;
        private double width;
        private double length;
        private double height;
               
     
        public double Area
        {
            get { return area; }
            set { area = value; }
        }
        public double Width
        {
            get { return width; }
            set { width = value; }
        }
        public double Length
        {
            get { return length; }
            set { length = value; }
        }

        public double Height
        {
            get { return height; }
            set { height = value; }
        }
     
        public BaseShape(double setLength, double setWidth, double setHight)
        {
            Width = setWidth;
            Length = setLength;
            Hight = setHeight;
        }

        abstract public void CalculateArea();

class TriangleShape : BaseShape
    {
        public TriangleShape(double length, double width, double height) : base(length, width,height) { }

        public override void CalculateArea()
        {
            Area = (0.5 * Height) * Length;
           
            Console.WriteLine("The Area of the Triangle is: {0:f2}", Area);

        }

    }


What I don't get is this. Why don't I have to downcast TriangleShape and RectangleShape when i assign them to the BaseShape variable?

like this:

Code:
class Program
    {
        static void Main(string[] args)
        {
            BaseShape myShape;
            myShape =(TriangleShape) new TriangleShape(3.0, 10.0, 10.0);
            myShape.CalculateArea();
            myShape =(RectangleShape) new RectangleShape(3.0, 10.0, 10.0);
            myShape.CalculateArea();
        }
    }


I thought you had to downcast each time you assign a Derived class to a base class variable?


Hardware: Ryzen 3700x, B450 MSI Gaming Pro carbon AC, GTX1080, 32 GB 3200 Mhz cas 14, 256 EVO SSD, 1 TB EVO SSD and 4 TB HDD.
Console: xbox, wii and xbox 360
Back to top
me7




Posts: 3942

PostPosted: Sun, 27th Feb 2011 00:30    Post subject:
myShape =(TriangleShape) new TriangleShape(3.0, 10.0, 10.0);

Are you sure this isn't a typo?
What's your motivation to cast a TriangleShape to TriangleShape?
Back to top
Werelds
Special Little Man



Posts: 15098
Location: 0100111001001100
PostPosted: Sun, 27th Feb 2011 00:31    Post subject:
Downcasting is going from base to derived, not derived to base - this is not downcasting Smile

In this case, Triangle and Rectangle both are a BaseShape (is-a relationship). They both have the same properties and methods as BaseShape; the mechanics behind them are perhaps different, but if you read your code, you can see that you don't care about the mechanic or specific implementation. All you're saying is that you want "some shape" which can do everything that Base can do; how it does it, or what else it can do is irrelevant to you.

Too tired to type it out in more detail atm Razz
Back to top
CraweN




Posts: 719
Location: Upside down in chair
PostPosted: Sun, 27th Feb 2011 08:24    Post subject:
me7 wrote:
myShape =(TriangleShape) new TriangleShape(3.0, 10.0, 10.0);

Are you sure this isn't a typo?
What's your motivation to cast a TriangleShape to TriangleShape?


Yeah your right, was typing this right before bed. Still new to programming so I'm gonna make a lot of mistakes! Some of them are gonna be fucking hilarious for others to read Very Happy


Hardware: Ryzen 3700x, B450 MSI Gaming Pro carbon AC, GTX1080, 32 GB 3200 Mhz cas 14, 256 EVO SSD, 1 TB EVO SSD and 4 TB HDD.
Console: xbox, wii and xbox 360
Back to top
CraweN




Posts: 719
Location: Upside down in chair
PostPosted: Sun, 27th Feb 2011 08:28    Post subject:
Alright, I'll post the important bit of the code that I was reading when I got into doubt about downcasting.

Code:
The hierarchy of the classes are as follows

Base Class is Employee
Derived Classes are SalariedEmployee, CommissionEmployee and HourlyEmployee
Lastly we have BasePlusCommissionEmployee which is derived from CommissionEmployee.

Code:
Employee[] employees = new Employee[ 4 ];


       employees[ 0 ] = salariedEmployee;         
       employees[ 1 ] = hourlyEmployee;           
       employees[ 2 ] = commissionEmployee;       
       employees[ 3 ] = basePlusCommissionEmployee;

       Console.WriteLine( "Employees processed polymorphically:\n" );


      foreach ( Employee currentEmployee in employees )
       {
          Console.WriteLine( currentEmployee ); // invokes ToString

          if ( currentEmployee is BasePlusCommissionEmployee )
          {


             BasePlusCommissionEmployee employee =
                ( BasePlusCommissionEmployee ) currentEmployee;

            employee.BaseSalary *= 1.10M;
            Console.WriteLine(
                "new base salary with 10% increase is: {0:C}",
                employee.BaseSalary );
          }


So in the for each loop, after checking if the currentEmployee IS a BasePlusCommissionEmployee, we set the currentEmployee as a BasePlusCommissionEmployee using a cast. Why? haven't we made sure that the "IS a" relationship is ok using the selection statement?


Hardware: Ryzen 3700x, B450 MSI Gaming Pro carbon AC, GTX1080, 32 GB 3200 Mhz cas 14, 256 EVO SSD, 1 TB EVO SSD and 4 TB HDD.
Console: xbox, wii and xbox 360
Back to top
me7




Posts: 3942

PostPosted: Sun, 27th Feb 2011 11:51    Post subject:
I guess that "employee.BaseSalary" is defined in the Base Class Employee, right? If my assumption is correct you are right to be confused since this cast is unnecessary. Loos like a bad example from a programming book that misses the point.

But if "employee.BaseSalary" is not defined in Employee but in BasePlusCommissionEmployee you need to cast to unveil BaseSalary to the compiler.
Some compilers don't require it though. They allow you to call any operations or members from objects and if you make a mistake the program crashes at runtime. C# (and a lot of others) have a feature that checks for the existence of operations based on the current declared type. Your variable is declared as Employee and even though it references a BasePlusCommissionEmployee the compiler views it as an Employee. When you want to call operations of BasePlusCommissionEmployee you need to cast explicitly.

Is this the answer you were looking for?
Back to top
LeoNatan
☢ NFOHump Despot ☢



Posts: 73242
Location: Ramat HaSharon, Israel 🇮🇱
PostPosted: Sun, 27th Feb 2011 11:59    Post subject:
This example would have worked better if the "1.10M" constant was a member of the BasePlusCommissionEmployee class (thus, each employee having his own commission).
Back to top
CraweN




Posts: 719
Location: Upside down in chair
PostPosted: Sun, 27th Feb 2011 19:50    Post subject:
me7 wrote:
I guess that "employee.BaseSalary" is defined in the Base Class Employee, right? If my assumption is correct you are right to be confused since this cast is unnecessary. Loos like a bad example from a programming book that misses the point.

But if "employee.BaseSalary" is not defined in Employee but in BasePlusCommissionEmployee you need to cast to unveil BaseSalary to the compiler.
Some compilers don't require it though. They allow you to call any operations or members from objects and if you make a mistake the program crashes at runtime. C# (and a lot of others) have a feature that checks for the existence of operations based on the current declared type. Your variable is declared as Employee and even though it references a BasePlusCommissionEmployee the compiler views it as an Employee. When you want to call operations of BasePlusCommissionEmployee you need to cast explicitly.

Is this the answer you were looking for?


Thanks, that helped. To answer your question method BaseSalary is defined in BasePlusCommissionEmployee, so the cast was needed.


Hardware: Ryzen 3700x, B450 MSI Gaming Pro carbon AC, GTX1080, 32 GB 3200 Mhz cas 14, 256 EVO SSD, 1 TB EVO SSD and 4 TB HDD.
Console: xbox, wii and xbox 360
Back to top
CraweN




Posts: 719
Location: Upside down in chair
PostPosted: Sun, 27th Feb 2011 19:52    Post subject:
Do any of you know if its possible to hide Comments in visual studio 2010? I find that sometimes it hinders readability of the different code examples.


Hardware: Ryzen 3700x, B450 MSI Gaming Pro carbon AC, GTX1080, 32 GB 3200 Mhz cas 14, 256 EVO SSD, 1 TB EVO SSD and 4 TB HDD.
Console: xbox, wii and xbox 360
Back to top
Page 1 of 1 All times are GMT + 1 Hour
NFOHump.com Forum Index - Programmers Corner
Signature/Avatar nuking: none (can be changed in your profile)  


Display posts from previous:   

Jump to:  
You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot vote in polls in this forum


Powered by phpBB 2.0.8 © 2001, 2002 phpBB Group