Click here to Skip to main content
15,890,946 members
Please Sign up or sign in to vote.
0.00/5 (No votes)
See more:
In the Code below when I convert or assign person2 to Employee which is a derived class there is no explicit casting required but when assign person1 to employee2 I need to cast it to Employee. My question is Employee class being a derived class has greater features than its base class, in this case how and why should we consider assigning person1 to employee2 (which requires casting) as a narrowing operation as mentioned in the MCSD C# certification Toolkit book.
Infact person class being ancestor has lesser features than Employee, So Employee object must be able to accommodate a person object without any explicit casting. Please elaborate.

C#
using System.IO;
using System;

class Program
{
    static void Main()
    {
        Employee employee1 = new Employee();
        Person person1 = employee1;
        Console.WriteLine("person1 name:{0}",person1.name);
        Person person2 = new Employee();
        // Allowed because person1 is actually an Employee.
        Employee employee2 = (Employee)person1;

    }
    class Person
    {
       public string name = "Unknown";
       public double salary = 0.00;
    }
    class Employee : Person
    {
      public string Designation = "New Comer";
    }
}
Posted

"Infact person class being ancestor has lesser features than Employee, So Employee object must be able to accommodate a person object without any explicit casting. Please elaborate."
No, it's the other way round.

Because Employee is derived from Person, a Person variable can freely contain an Employee (or any other class derived from Person) because all such classes must contain everything that the Person class does. So the system can safely access all the fields, properties, methods, events, and so forth from the Person class without any problems.

But to go the other way invites run time errors! Let's take your example, and turn it round:
C#
Employee emp = new Person();  // The compiler will complain here, but if it didn't...
string des = emp.Designation;
Because emp refers to an Employee, Designation is available. But we assigned a Person to the variable - which doesn't have a Designation field, so what is the system supposed to access?

That's why you have to explicitly cast: so that the system can be sure when it accesses derived class features that the class instance actually supports them! The run time cast will fail if the features will not be available because you can't "up-cast" a Person instance to an derived Employee.


"Considering these lines:-
C#
Employee employee1 = new Employee();
Person person1 = employee1;
Console.WriteLine("person1 name:{0}",person1.name);
Person person2 = new Employee();
// Allowed because person1 is actually an Employee.
Employee employee2 = (Employee)person1;

If I write person.Designation in the WriteLine statement it throws a compile time error. But again when I reassign the person1 to Employee object (employee2) the employee2 can be used to access Designation. Now when I assigned the employee1 to person1 what happens to the Designation field. Because in the first WriteLine I could never access Designation using person1(naturally) because it is person. But then what happens to the Designation field which appears back when I assign employee2 with person1(casted). Hope you understand what I intend to say.

Say I had Data in the employee object which I assigned to person1, will that be persistent when I use person1 in the 5th statement. Will this be a good technique in any manner in software development practice?"



If you write person.Designation you get a compiler error, because Designation is not a field of the Person class - and person is a variable which can reference any Person instance - so you an only access properties, fields, and such like that are part of every Person, and not those which are only part of a derived class.

When you cast an instance, you don't change the data, you just change how the system sees the data. Any derived class added information remains a part of the instance.

Think about it with cars.
A Ford is a Car
A Fiesta is a Ford, which is a Car.
A Mondeo is a Ford, which is a Car.

You can say "My Car" and mean a Fiesta, a Mondeo, or a Mercedes A-Class without changing the type of car you drive!
Equally, you can say "My Ford" and mean either a fiesta or a Mondeo, but you can't say "My Ford" and drive away in a Mercedes! :laugh:

The same thing applies to your Person and Employee classes: the variable type that references the instance doesn't change the type of the instance it references, it just controls what you can do with it without casting it to a different type.

It's a very useful practice: it allows you to create a Person class, derive Employee and Customer classes from that, and have a table which can hold both:
C#
List<Person> myList = new List<Person>();
myList.Add(new Employee("Joe Brown"));
myList.Add(new Customer("Mary Shelley"));

The Person class would have the Name and Address - but the Employee would have Salary while the Customer would have DeliveryCost

Make sense?
 
Share this answer
 
v2
Comments
ganesh.dks 13-Aug-15 4:50am    
Considering these lines:-
Employee employee1 = new Employee();
Person person1 = employee1;
Console.WriteLine("person1 name:{0}",person1.name);
Person person2 = new Employee();
// Allowed because person1 is actually an Employee.
Employee employee2 = (Employee)person1;
If I write person.Designation in the WriteLine statement it throws a compile time error. But again when I reassign the person1 to Employee object (employee2) the employee2 can be used to access Designation. Now when I assigned the employee1 to person1 what happens to the Designation field. Because in the first WriteLine I could never access Designation using person1(naturally) because it is person. But then what happens to the Designation field which appears back when I assign employee2 with person1(casted). Hope you understand what I intend to say.

Say I had Data in the employee object which I assigned to person1, will that be persistent when I use person1 in the 5th statement. Will this be a good technique in any manner in software development practice?
OriginalGriff 13-Aug-15 5:12am    
Answer updated
See solution one.

Interfaces work a little differently. They are not an object assigned into memory, but just pointers to an existing objects memory.

Take a look at this:

C#
private static void Main()
{
    Employee employee1 = new Employee();
    IPerson person1 = employee1;
    Console.WriteLine("person1 name:{0}", person1.Name);
    Person person2 = new Employee();
    // Allowed because person1 is actually an Employee.
    IPerson employee2 = person2;
    IPerson employee3 = employee1;

    Console.WriteLine("employee2 name:{0}", employee2.Name);
    Console.WriteLine("employee2 name:{0}", employee3.Name);

}

private interface IPerson
{
    string Name { get; set; }
    double Salary { get; set; }

}

private class Person : IPerson
{
    private string name = "Unknown";
    private double salary = 0.00;

    public string Name
    {
        get { return name; }
        set { name = value; }
    }

    public double Salary
    {
        get { return salary; }
        set { salary = value; }
    }
}

private class Employee : Person
{
    public string Designation = "New Comer";
}


I have added an interface IPerson, which Person implements (by the transitive nature of inheritance, so does Employee)

I can now use this interface to represent the object. I can access the Name object of any employee or person cast as IPerson, but the Designation. I would have to upcast from IPerson to Employee.

This leave a new issue. What is the object represented by IPerson is not an Employee object? I can cast it but then I don't know what it was to begin with. I can use safe casting and test it:

C#
Employee employeeToCheck = employee2 as Employee;
if(employeeToCheck != null)
 {
    //cast successful
 }
else
 {
    //cast failed.  employee2 was not an employee object
 }


You can use this to test, or you can check the "is" statement:
C#
if(employee2 is Employee)


There are lots of ways using reflection to check the type and it's inheritances etc.

Hope that helps ^_^

Andy
 
Share this answer
 
v2

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