A layer of replacement is introduced between classes. Replacement means that the instance of one class can be replaced with the instance of another class. For example, in a class hierarchy, where parent classes are used, we can replace them with subclass instances. This is a "polymorphism.
When we define a type conversion operator for the type, we are actually telling the compiler that these types can be used as the target type. Such replacement often leads to some strange bugs, because our type may not be a perfect alternative to the target type.
Let's take a look at the following code.
Code
1 public abstract class Employee
2 {
3 private string m_strName;
4 public string Name
5 {
6 get { return m_strName; }
7 set { m_strName = value; }
8 }
9
10 private float m_fSalary;
11 public float BaseSalary
12 {
13 get { return m_fSalary; }
14 set { m_fSalary = value; }
15 }
16
17 public Employee(string name, float salary)
18 {
19 m_strName = name;
20 m_fSalary = salary;
21 }
22
23 public Employee()
24 {}
25 }
26
27 public class Sales : Employee
28 {
29 public Sales(string name, float salary)
30 : base(name, salary)
31 { }
32
33 public Sales(Manager manager)
34 {
35 base.Name = manager.Name;
36 base.BaseSalary = manager.BaseSalary;
37 }
38 }
39
40 public class Manager : Employee
41 {
42 public Manager(string name, float salary)
43 : base(name, salary)
44 { }
45
46 public static implicit operator Sales(Manager obj)
47 {
48 return new Sales(obj.Name, obj.BaseSalary) ;
49 }
50 }
The code above defines three structures, in which, as the top-level type, employee is defined as abstract. It has two Derived classes: Sales and manager, specifically, manger provides type conversion to sales.
The following is the code of the test method.
Code
1 private static void Test()
2 {
3 Sales sales = new Sales("Wing", 2000);
4 Manager manager = new Manager("UnKnown", 2000);
5 Console.WriteLine("The First Test : Output info:");
6 OuputInfo(sales);
7 OuputInfo(manager);
8 Console.WriteLine();
9 Console.WriteLine("The Second Test : Double Salary:");
10 Console.WriteLine("Before Double : ");
11 Console.WriteLine(sales.BaseSalary);
12 Console.WriteLine(manager.BaseSalary);
13 DoubleSalary(sales);
14 DoubleSalary(manager);
15 Console.WriteLine("After Double : ");
16 Console.WriteLine(sales.BaseSalary);
17 Console.WriteLine(manager.BaseSalary);
18 }
19
20 private static void DoubleSalary(Sales sales)
21 {
22 sales.BaseSalary *= 2;
23 }
24
25 private static void OuputInfo(Sales sales)
26 {
27 Console.WriteLine(string.Format("Employee Info : {0}", sales.Name));
28 }
The code above contains three methods. The test () method is the main method for testing, the outputinfo () method is used to output employee information, doublesalary () the method is used to multiply the basesalary attribute in the object by 2 (haha, it's coming soon, even if it's my New Year's wish ^_^ ).
Shows the execution result of the above Code.
We can see that for the outputinfo () method testing, the sales object and the manager object are correct, but the test results of doublesalary () method are problematic. After the doublesalary () method is called, The basesalary attribute of sales is indeed doubled, but the basesalary attribute of manager is not changed.
This is because an implicit type conversion occurs when the manager object is passed into the doublesalary () method, that is, the manager type is changed to the sales type, at this time, a new temporary object will be created, and various operations in the doublesalary () method are aimed at temporary objects. After exiting the doublesalary () method, the temporary object will become garbage, it will be recycled by the garbage collector later.
In fact, the execution results of the following three statements are the same.
DoubleSalary(manager);
DoubleSalary((Sales)manager);
DoubleSalary(new Sales(manager));
If you want to solve this problem, you need to write the code as below.
Sales temp = new Sales(manager);
DoubleSalary(temp);
After the above code is executed, the basesalary attribute of the temp object has doubled.
Summary: The "Replacement" obtained by the conversion operator brings some problems to the code. The conversion operator is provided to indicate to the class users that the class should have been used, you can use other types instead. When accessing a replaced object, some temporary objects or internal fields are actually used in dealing with the client program. After these temporary objects are modified, the results will be discarded. This strange bug is hard to find, because the code for type conversion is generated by the compiler, so we should avoid using type conversion characters.