WEB开发网
开发学院软件开发C语言 Effective C# 原则28:避免转换操作 阅读

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

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很难发现。应该尽量避免转换操作。

上一页  1 2 3 

Tags:Effective 原则 避免

编辑录入:爽爽 [复制链接] [打 印]
赞助商链接