Effective C# Item27:避免ICloneable接口

    一般情况下,我们不建议针对类型实现ICloneable接口。因为如果一个类型支持ICloneable接口,那么该类型的所有派生类都必须实现它,而且类型中所有成员类型也都要实现ICloneable接口,或者有其他创建复制对象的机制,当我们设计的类型包含交织成网状的对象时,支持深复制会变得比较复杂。

    复制操作分为浅复制和深复制两种,其中浅复制是指新对象包含所有成员变量的副本,如果成员变量为引用类型,那么新对象将和原对象引用同样的对象;深复制中新对象也包含所有成员变量的副本,但是所有引用类型的成员变量都会被递归的复制。对于C#来说,内建类型,例如整型,执行深复制和浅复制的结果是相同的。

    任何只包含内建类型成员的值类型都不需要实现ICloneable接口,一个简单的赋值语句要比Clone()方法效率更高,因为Clone()方法必须对返回值进行装箱,才能转换成一个System.Object引用。

    而对于引用类型来说,如果引用类型需要通过实现ICloneable接口的方式来表明自身支持浅复制或者深复制,这时,该类型的派生类也必须实现ICloneable接口。

    来看下面的代码。

class BaseType : ICloneable
{
  private string _label = "class name";
  private int [] _values = new int [ 10 ];

  public object Clone()
  {
    BaseType rVal = new BaseType( );
    rVal._label = _label;
    for( int i = 0; i < _values.Length; i++ )
      rVal._values[ i ] = _values[ i ];
    return rVal;
  }
}

 class Derived : BaseType
{
  private double [] _dValues = new double[ 10 ];

  static void Main( string[] args )
  {
    Derived d = new Derived();
    Derived d2 = d.Clone() as Derived;

    if ( d2 == null )
      Console.WriteLine( "null" );
  }

    上述代码在运行后,我们会发现d2的值时null,这是因为Derived类从BaseType类继承了Clone()方法,但是继承来的实现对Derived类型来说是不正确的,因为它只是克隆了基类,BaseType.Clone()方法创建了一个BaseType类型的对象,而不是一个Derived类型的对象。

    如果需要解决这个问题,我们可以将BaseType类中的Clone()方法声明为abstract,这样所有的派生类都必须实现这个方法。另外,我们还可以通过以下的方式来解决这个问题。

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接口。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
ava实现的毕业设计&&课程设计(包含运行文档+数据库+前后端代码),可运行高分资源 Java实现的毕业设计&&课程设计(包含运行文档+数据库+前后端代码),Java实现的毕业设计&&课程设计(包含运行文档+数据库+前后端代码),Java实现的毕业设计&&课程设计(包含运行文档+数据库+前后端代码),Java实现的毕业设计&&课程设计(包含运行文档+数据库+前后端代码),Java实现的毕业设计&&课程设计(包含运行文档+数据库+前后端代码),Java实现的毕业设计&&课程设计(包含运行文档+数据库+前后端代码),Java实现的毕业设计&&课程设计(包含运行文档+数据库+前后端代码),Java实现的毕业设计&&课程设计(包含运行文档+数据库+前后端代码),Java实现的毕业设计&&课程设计(包含运行文档+数据库+前后端代码),Java实现的毕业设计&&课程设计(包含运行文档+数据库+前后端代码),Java实现的毕业设计&&课程设计(包含运行文档+数据库+前后端代码),Java实现的毕业设计&&课程设计(包含运行文档+数据库+前后端代码),Java实现的毕业设计&&课程设计(包含运行文档+数据库+前后端代码),Java实现的毕业设计&&课程设计(包含运行文档+数据库+前后端代码),Java实现的毕业设计&&课程设计(包含运行文档+数据库+前后端代码),Java实现的毕业设计&&课程设计(包含运行文档+数据库+前后端代码),Java实现的毕业设计&&课程设计(包含运行文档+数据库+前后端代码),Java实现的毕业设计&&课程设计(包含运行文档+数据库+前后端代码),Java实现的毕业设计&&课程设计(包含运行文档+数据库+前后端代码),Java实现的毕业设计&&课程设计(包含运行文档+数据库+前后端代码),Java实现的毕业设计&&课程设计(包含运行文档+数据库+前后端代码),Java实现的毕业设计&&课程设计(包含运行文档+数据库+前后端代码),Java实现的毕业设计&&课程设计(包含运行文档+数据库+前后端代码),Java实现的毕业设计&&课程设计(包含运行文档+数据库+前后端代码),Java实现的毕业设计&&课程设计(包含运行文档+数据库+前后端代码),Java实现的毕业设计&&课程设计(包含运行文档+数据库+前后端代码),Java实现的毕业设计&&课程设计(包含运行文档+数据库+前后端代码),Java实现的毕业设计&&课程设计(包含运行文档+数据库+前后端代码),Java实现的毕业设计&&课程设计(包含运行文档+数据库+前后端代码),Java实现的毕业设计&&课程设计(包含运行文档+数据库+前后端代码),Java实现的毕业设计&&课程设计(包含运行文档+数据库+前后端代码),Java实现的毕业设计&&课程设计(包含运行文档+数据库+前后端代码),Java实现的毕业设计&&课程设计(包含运行文档+数据库+前后端代码),Java实现的毕业设计&&课程设计(包含运行文档+数据库+前后端代码),Java实现的毕业设计&&课程设计(包含运行文档+数据库+前后端代码),Java实现的毕业设计&&课程设计(包含运行文档+数据库+前后端代码),Java实现的毕业设计&&课程设计(包含运行文档+数据库+前后端代码),Java实现的毕业设计&&课程设计(包含运行文档+数据库+前后端代码),Java实现的毕业设计&&课程设计(包含运行文档+数据库+前后端代码),Java实现的毕业设计&&课程设计(包含运行文档+数据库+前后端代码),Java实现的毕业设计&&课程设计(包含运行文档+数据库+前后端代码),Java实现的毕业设计&&课程设计(包含运行文档+数据库+前后端代码),Java实现的毕业设计&&课程设计(包含运行文档+数据库+前后端代码),Java实现的毕业设计&&课程设计(包含运行文档+数据库+前后端代码),Java实现的毕业设计&&课程设计(包含运行文档+数据库+前后端代码),Java实现的毕业设计&&课程设计(包含运行文档+数据库+前后端代码),Java实现的毕业设计&&课程设计(包含运行文档+数据库+前后端代码),Java实现的毕业设计&&课程设计(包含运行文档+数据库+前后端代码),Java实现的毕业设计&&课程设计(包含运行文档+数据库+前后端代码),Java实现的毕业设计&&课程设计(包含运行文档+数据库+前后端代码),Java实现的毕业设计&&课程设计(包含运行文档+数据库+前后端代码),Java实现的毕业设计&&课程设计(包含运行文档+数据库+前后端代码),Java实现的毕业设计&&课程设计(包含运行文档+数据库+前后端代码),Java实现的毕业设计&&课程设计(包含运行文档+数据库+前后端代码),Java实现

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值