Effective C# 原则28:避免转换操作
2009-02-19 08:16:17 来源:WEB开发网public void Flatten( Ellipse e )
{
e.R1 /= 2;
e.R2 *= 2;
}
// call it using a circle:
Circle c = new Circle( new PointF ( 3.0f, 0 ), 5.0f );
Flatten( c );
这是无效的,Flatten()方法要求一个椭圆做为参数,编译器必须以某种方式把圆形转化为椭圆。确实,也已经实现了一个隐式的转换。而且你转换也被调用了,Flatten()方法得到的参数是从你的转换操作中创建的新的椭圆对象。这个临时对象被Flatten()函数修改,而且它很快成为垃圾对象。正是因为这个临时对象,Flatten()函数产生了副作用。最后的结果就是这个圆形对象,c,根本就没有发生任何改变。从隐式转换修改成显示转换也只是强迫用户调用强制转换而以:
Circle c = new Circle( new PointF( 3.0f, 0 ), 5.0f );
Flatten( ( Ellipse ) c );
原先的问题还是存在。你想让用户调用强制转换为解决这个问题,但实际上还是产生了临时对象,把临时对象进行变平(flatten)操作后就丢掉了。原来的圆,c,还是根本没有被修改过。取而代之的是,如果你创建一个构造函数把圆形转换成椭圆,那么操作就很明确了:
Circle c = new Circle( new PointF( 3.0f, 0 ), 5.0f );
Flatten ( new Ellipse( c ));
相信很多程序员一眼就看的出来,在前面的两行代码中传给Flatten()的椭圆在修改后就丢失了。他们可能会通过跟踪对象来解决这个问题:
Circle c = new Circle( new PointF( 3.0f, 0 ), 5.0f );
// Work with the circle.
// ...
// Convert to an ellipse.
Ellipse e = new Ellipse( c );
Flatten( e );
通过一个变量来保存修改(变平)后的椭圆,通过构造函数来替换转换操作,你不会丢失任何功能:你只是让创建新对象的操作更加清楚。(有经验的C++程序可能注意到C#的隐式转化和显示转换都没有调用构造函数。在C++中,只有明确的使用new操作符才能创建一个新的对象时,其它时候不行。而在C#的构造函数中不用明确的使用关键字。)
从类型里返回字段的转换操作并不会展示类型的行为,这会产生一些问题。你给类型的封装原则留下了几个严重的漏洞。通过把类型强制转化为其它类型,用户可以访问到类型的内部变量。这正是原则23中所讨论的所有原因中最应该避免的。
转换操作提供了一种类型可替代的形式,但这会给代码引发一些问题。你应该已经明白所有这些内容:用户希望可以合理的用某种类型来替代你的类型。当这个可替代类型被访问时,你就让用户在临时对象上工作,或者内部字段取代了你创建的类。随后你可能修改了临时对象,然后丢掉。因为这些转换代码是编译器产生的,因此这些潜在的BUG很难发现。应该尽量避免转换操作。
- ››避免在代码中直接任意使用ConfigurationManager.A...
- ››避免推广中出现负面信息的6个有效方法
- ››避免地方门户网站运营转型过程中的管理误区
- ››避免刷新页面,自动跳回到页面顶部的办法
- ››避免重复代码——know your library
- ››避免重复代码——know your library(续)
- ››避免遭受攻击 七个技巧保护服务器安全
- ››Effective C# 原则40:根据需求选择集合
- ››Effective C# 原则41:选择DataSet而不是自定义的...
- ››Effective C# 原则42:使用特性进行简单的反射
- ››Effective C# 原则43:请勿滥用反射
- ››Effective C# 原则44:创建应用程序特定的异常类
更多精彩
赞助商链接