Effective C# 原则27:避免使用ICloneable
2009-02-19 08:16:19 来源:WEB开发网如果你运行这个程序,你就会发现d2为null。虽然Derived是从BaseType派生的,但从BaseType类继承的Clone()函数并不能正确的支持Derived类:它只拷贝了基类。BaseType.Clone()创建的是一个BaseType对象,不是派生的Derived对象。这就是为什么程序中的d2为null而不是派生的Derived对象。即使你克服了这个问题,BaseType.Clone()也不能正确的拷贝在Derived类中定义的_dValues数组。一但你实现了ICloneable, 你就强制要求所有派生类也必须正确的实现它。实际上,你应该提供一个hook函数,让所有的派生类使用你的拷贝实现(参见原则21)。在拷贝时,派生类可以只对值类型成员或者实现了ICloneable接口的引用类型成员进行拷贝。对于派生类来说这是一个严格的要求。在基类上实现ICloneable接口通常会给派生类添加这样的负担,因此在密封类中应该避免实现ICloneable 接口。
因此,当整个继承结构都必须实现ICloneable时,你可以创建一个抽象的Clone()方法,然后强制所有的派生类都实现它。
在这种情况下,你需要定义一个方法让派生类来创建基类成员的拷贝。可以通过定义一个受保护的构造函数来实现:
class BaseType
{
private string _label;
private int [] _values;
protected BaseType( )
{
_label = "class name";
_values = new int [ 10 ];
}
// Used by devived values to clone
protected BaseType( BaseType right )
{
_label = right._label;
_values = right._values.Clone( ) as int[ ] ;
}
}
sealed class Derived : BaseType, ICloneable
{
private double [] _dValues = new double[ 10 ];
public Derived ( )
{
_dValues = new double [ 10 ];
}
// Construct a copy
// using the base class copy ctor
private Derived ( Derived right ) :
base ( right )
{
_dValues = right._dValues.Clone( )
as double[ ];
}
static void Main( string[] args )
{
Derived d = new Derived();
Derived d2 = d.Clone() as Derived;
if ( d2 == null )
Console.WriteLine( "null" );
}
public object Clone()
{
Derived rVal = new Derived( this );
return rVal;
}
}
基类并不实现ICloneable接口; 通过提供一个受保护的构造函数,让派生类可以拷贝基类的成员。叶子类,应该都是密封的,必要它应该实现ICloneable接口。基类不应该强迫所有的派生类都要实现ICloneable接口,但你应该提供一些必要的方法,以便那些希望实现ICloneable接口的派生类可以使用。
ICloneable接口有它的用武之地,但相对于它的规则来说,我们应该避免它。对于值类型,你不应该实现ICloneable接口,应该使用赋值语句。对于引用类型来说,只有在拷贝确实有必要存在时,才在叶子类上实现对ICloneable的支持。基类在可能要对ICloneable 进行支持时,应该创建一个受保护的构造函数。总而言之,我们应该尽量避免使用ICloneable接口。
- ››避免在代码中直接任意使用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:创建应用程序特定的异常类
更多精彩
赞助商链接