0

As per my understanding if I have a parent class type reference variable pointing to a child class object :

ParentClass obj= new ChildClass();

obj.OnlyMembersThatHavebeenDerivedFromParentAreAvailable// am i wrong? 

In the below example which i have taken from click here I should not be able to access AnnualSalary

Derived Class:

 public class FullTimeEmployee : Employee
    {
        public int AnnualSalary { get; set; }
    }

Derived Class:

public class PartTimeEmployee : Employee
    {
        public int HourlyPay { get; set; }
        public int HoursWorked { get; set; }
    }

Parent Class

 public class Employee
    {
        private int _id;
        private string _name;
        private string _gender;
        private DateTime _dateOfBirth;

        [DataMember(Order = 1)]
        public int Id
        {
            get { return _id; }
            set { _id = value; }
        }

        [DataMember(Order = 2)]
        public string Name
        {
            get { return _name; }
            set { _name = value; }
        }

        [DataMember(Order = 3)]
        public string Gender
        {
            get { return _gender; }
            set { _gender = value; }
        }

        [DataMember(Order = 4)]
        public DateTime DateOfBirth
        {
            get { return _dateOfBirth; }
            set { _dateOfBirth = value; }
        }

        [DataMember(Order = 5)]
        public EmployeeType Type { get; set; }
    }

How is the following code valid? :

Employee employee = null;
 employee = new FullTimeEmployee
                        {
                            Id = Convert.ToInt32(reader["Id"]),
                            Name = reader["Name"].ToString(),
                            Gender = reader["Gender"].ToString(),
                            DateOfBirth = Convert.ToDateTime(reader["DateOfBirth"]),
                            Type = EmployeeType.FullTimeEmployee,
                            AnnualSalary = Convert.ToInt32(reader["AnnualSalary"]) // how is AnnualSalary available here? 
                        };
SamuraiJack
  • 5,131
  • 15
  • 89
  • 195
  • 1
    Are you having problems with it? Does it compile? – Mark Seemann Dec 20 '15 at 14:33
  • I did not recreate this in visual studio. I was watching a video tutorial from this same blogger (uses this exact same code which is on that blog ) and he was able to successfully compile and run it. So yes it does compile. But how come? – SamuraiJack Dec 20 '15 at 14:35

1 Answers1

2

You are right, you cannot write:

employee.AnnualSalary = 1234;

But this is not your case.
You are just using an object initializer to initialize a FullTimeEmployee object(You have access to all public fields/properties).
Basically you are doing the following:

FullTimeEmployee employeeTemp = new FullTimeEmployee();
employeeTemp .AnnualSalary =2000;
Employee employee =employeeTemp;

Update

I thought one can not typecast parent class object to child class object since a child can do everything that parent can but vice versa is not true.

Once again you are right.
And once again this is not your case...
The return type of the method might be Employee but the actual object you return might be something else (a derived class).
In this case you can safely cast the object to your derived type.
Check the following example

namespace CastExample
{
  class Program
  {
    static void Main(string[] args)
    {
        Employee emp = GetEmployee();
        FullTimeEmployee full = (FullTimeEmployee)emp;
        System.Console.WriteLine(full.AnnualSalary);
        PartTimeEmployee part = (PartTimeEmployee)emp;//InvalidCastException
        System.Console.ReadLine();
    }

    static Employee GetEmployee()
    {
        return new FullTimeEmployee() { Name = "George", AnnualSalary = 1234   };
    }
  }
  public class Employee
  {
     public string Name;
  }
  public class FullTimeEmployee : Employee
  {
     public int AnnualSalary { get; set; }
  }
  public class PartTimeEmployee : Employee
  {
      public int HourlyPay { get; set; }
      public int HoursWorked { get; set; }
  }
}

And he can access private properties too??

Yes,you can access private fields using reflection
Find a private field with Reflection?
How to get the value of private field in C#?
c# use reflection to get a private member variable from a derived class

Check this : Why can reflection access protected/private member of class in C#?
@Marc Gravell's answer explain why you can do this but pay special attention to @Tamas Czinege's answer (I quote it here again)

Member accessibility is not a security feature. It is there to protect the programmer against himself or herself. It helps implementing encapsulation but it is by no means a security feature.

Community
  • 1
  • 1
George Vovos
  • 7,563
  • 2
  • 22
  • 45
  • OH! I get it now. Damn initializer syntax! Btw just to be sure if my method return this `employee` object. There is no way caller can access AnnualSalary right? Assigning value to to AnnualSalary would be in vain in this particular scenario right? – SamuraiJack Dec 20 '15 at 15:33
  • @Arbaaz If your method returns an object of type Employee the caller cannot access AnnualSalary using the . notation .**BUT** the caller can cast the object to FullTimeEmployee and then access all the public properties of FullTimeEmployee class ,including AnnualSalary.(He can very easily access the private properties also ...) – George Vovos Dec 21 '15 at 16:08
  • Are you sure? I mean I thought one can not typecast parent class object to child class object since a child can do everything that parent can but vice versa is not true. And he can access private properties too?? How? I am sorry its kind of out of context but I need to know how. – SamuraiJack Dec 21 '15 at 16:14
  • @Arbaaz ,see my updated answer.If you have more questions close this one and ask new ones – George Vovos Dec 22 '15 at 08:48
  • thank you I did not really know private fields can be accessed in this way. – SamuraiJack Dec 26 '15 at 06:49