Effective C# Item28:避免强制类型转换
来源:互联网 发布:国际经济合作 数据 编辑:程序博客网 时间:2024/06/05 15:37
转换操作为类之间引入了一层“可替换性”,“替换”意味着一个类的实例可以被替换为另一个类的实例。例如,我们在一个类层次结构中,在任何使用父类的地方,我们可以使用子类的实例进行替代,这是“多态”的作用。
当我们为类型定义了类型转换操作符后,我们实际上是在告诉编译器这些类型可以被当做目标类型来使用,这样的替换经常会导致一些很诡异的Bug,因为我们的类型可能并不是目标类型的完美替代品。
我们来看下面的代码。
public abstract class Employee { private string m_strName; public string Name { get { return m_strName; } set { m_strName = value; } } private float m_fSalary; public float BaseSalary { get { return m_fSalary; } set { m_fSalary = value; } } public Employee(string name, float salary) { m_strName = name; m_fSalary = salary; } public Employee() {} } public class Sales : Employee { public Sales(string name, float salary) : base(name, salary) { } public Sales(Manager manager) { base.Name = manager.Name; base.BaseSalary = manager.BaseSalary; } } public class Manager : Employee { public Manager(string name, float salary) : base(name, salary) { } public static implicit operator Sales(Manager obj) { return new Sales(obj.Name, obj.BaseSalary) ; } }
上面的代码定义了三个结构,其中Employee作为最上层的类型,被定义为abstract,它下面有两个派生类Sales和Manager,其中针对Manger向Sales提供了类型转换。
下面是测试方法的代码。
private static void Test() { Sales sales = new Sales("Wing", 2000); Manager manager = new Manager("UnKnown", 2000); Console.WriteLine("The First Test : Output info:"); OuputInfo(sales); OuputInfo(manager); Console.WriteLine(); Console.WriteLine("The Second Test : Double Salary:"); Console.WriteLine("Before Double : "); Console.WriteLine(sales.BaseSalary); Console.WriteLine(manager.BaseSalary); DoubleSalary(sales); DoubleSalary(manager); Console.WriteLine("After Double : "); Console.WriteLine(sales.BaseSalary); Console.WriteLine(manager.BaseSalary); } private static void DoubleSalary(Sales sales) { sales.BaseSalary *= 2; } private static void OuputInfo(Sales sales) { Console.WriteLine(string.Format("Employee Info : {0}", sales.Name)); }
上面的代码包含了三个方法,其中Test()方法是测试的主方法,OutputInfo()方法用于输出员工的信息,DoubleSalary()方法用于将对象中的BaseSalary属性乘2(呵呵,快过年了,这就算是我的新年愿望啦^_^)。
上述代码的执行结果如下图所示。
我们可以看到,对于针对OutputInfo()方法进行的测试,Sales对象和Manager对象的结果是正确的;但是对于DoubleSalary()方法的测试结果,就有问题了。在调用DoubleSalary()方法后,Sales的BaseSalary属性确实变为之前的2倍了,但是Manager的BaseSalary属性并没有发生变化。
之所以出现这种情况,是因为当将Manager对象传入DoubleSalary()方法中时,发生了隐式类型转换,即将Manager类型转变为Sales类型,这时会创建出一个新的临时对象,而DoubleSalary()方法中的各种操作,都是针对临时对象的,在退出DoubleSalary()方法后,临时对象变为垃圾,在稍后就会被垃圾回收器进行回收处理。
其实下面三句话的执行结果是一样的。
DoubleSalary(manager);DoubleSalary((Sales)manager);DoubleSalary(new Sales(manager));
如果希望解决这个问题,需要将代码写成下面的样子。
Sales temp = new Sales(manager);DoubleSalary(temp);
上面代码执行后,temp对象的BaseSalary属性已经翻倍了。
总结:转换操作符所获得的“替换性”会为代码带来一些问题,提供转换操作符的意思是在向类的用户表明,在本该使用这个类的地方,用户可以使用其他类型来代替。当访问被替换的对象时,和客户程序打交道的实际上时一些临时对象或者内部字段。这些临时对象被修改后,结果就会被抛弃。这样诡异的bug是很难发现的,因为进行类型转换的代码是由编译器产生的,因此我们应该避免使用类型转换符。
- Effective C# Item28:避免强制类型转换
- C#中强制类型转换
- C# Bug --强制类型转换
- C#的强制类型转换
- C#自定义类型强制转换
- Effective C# 原则3:选择is或者as操作符而不是做强制类型转换
- Effective C++ (7) 强制类型转换
- 利用泛型避免工厂方法强制类型转换
- 《Effective C++》读书笔记之item28:避免返回handles指向对象内部成分
- 《Effective C#》 Item 28: 避免使用类型转换操作符
- C++与C#对比:强制类型转换
- C#基础-类型强制转换,拆箱,装箱
- C#自定义类型的强制转换
- C# int类型的强制转换整理
- C#的类型转换:显示类型转换、强制类型转换、不兼容类型转换
- 关于强制类型转换:强制类型转换
- 类型转换&&类型强制转换
- 类型转换&&类型强制转换
- HDU 2047 阿牛的EOF牛肉串
- RunTime之三
- javascript 下拉列表 自动取值 无需value
- SDN入门资料
- 数据库系统概论-[01]关系型数据库标准SQL
- Effective C# Item28:避免强制类型转换
- eclipse中访问不了tomcat首页server Locations变灰无法编辑
- RunTime之四
- 函数指针
- Python入门(一,Ubuntu环境搭建)
- 大家好,我是新来的
- Service ser = new Service()报错问题
- 实体类实现根据指定属性进行排序
- C++ STL轻松导学