First few tests to understand the basics:
What do you think about the GetEmployeeType() method that will be called - will it be on Employee class or Manager class?
What do you think about the GetEmployeeType() method that will be called - will it be on Employee class or Manager class?
void Main() { Employee e = new Manager(); Console.WriteLine(e.GetEmployeeType()); } class Employee { public virtual string GetEmployeeType() { return nameof(Employee); } } class Manager : Employee { public override string GetEmployeeType() { return nameof(Manager); } }
Output: Manager
Since Employee object 'e' points to Manager, it will call the GetEmployeeType of Manager class.
Another one:
void Main() { Employee employee = new Manager(); Console.WriteLine(CalculateSalary(employee)); } string CalculateSalary(Employee e) { return $"{nameof(CalculateSalary)} of {nameof(Employee)}"; } string CalculateSalary(Manager e) { return $"{nameof(CalculateSalary)} of {nameof(Manager)}"; } class Employee ... class Manager : Employee ...
Output: CalculateSalary of Employee
Since the object is of type Employee the CalculateSalary accepting Employee will be called.
Taking this further, let's move the CalculateSalary to a class.
void Main() { Employee employee = new Employee(); Employee manager = new Manager(); SalaryAlgo algo = new SalaryAlgoBasedOnPerformance(); Console.WriteLine(algo.CalculateSalary(employee)); Console.WriteLine(algo.CalculateSalary(manager)); } class SalaryAlgo { public virtual string CalculateSalary(Employee e) { return $"{nameof(CalculateSalary)} of {nameof(Employee)} based on {nameof(SalaryAlgo)}"; } public virtual string CalculateSalary(Manager e) { return $"{nameof(CalculateSalary)} of {nameof(Manager)} based on {nameof(SalaryAlgo)}"; } } class SalaryAlgoBasedOnPerformance : SalaryAlgo { public override string CalculateSalary(Employee e) { return $"{nameof(CalculateSalary)} of {nameof(Employee)} based on {nameof(SalaryAlgoBasedOnPerformance)}"; } public override string CalculateSalary(Manager e) { return $"{nameof(CalculateSalary)} of {nameof(Manager)} based on {nameof(SalaryAlgoBasedOnPerformance)}"; } } class Employee ... class Manager : Employee ...
Output:
CalculateSalary of Employee based on SalaryAlgoBasedOnPerformance CalculateSalary of Employee based on SalaryAlgoBasedOnPerformance
As you can see, CalculateSalary(Manager) is not at all called. This is because the method to call is decided at compile time and the declared type is used to identify the method not the runtime type.
A quick way to fix this is to use "dynamic" keyword:
Console.WriteLine(algo.CalculateSalary((dynamic)manager));
Output:
CalculateSalary of Employee based on SalaryAlgoBasedOnPerformance CalculateSalary of Manager based on SalaryAlgoBasedOnPerformance
Another way to resolve this is to use Visitor pattern.
Helpful links:
https://blogs.msdn.microsoft.com/curth/2008/11/15/c-dynamic-and-multiple-dispatch/
EDIT: Post that implements Visitor pattern to resolve this problem.
No comments:
Post a Comment
Note: only a member of this blog may post a comment.