Effective C # Principle 27: Avoid using icloneable

Source: Internet
Author: User
Tags shallow copy

ICloneable seems like a good idea: After implementing the ICloneable interface for a type, you can support copying. If you don't want to support copying, don't implement it.

But your object does not run in a "vacuum" environment, but it is best to support icloneable, given some of the effects on derived classes. Once a type supports icloneable, all derived classes must be consistent, that is, all members must support the ICloneable interface or provide a mechanism to support the copy. Finally, objects that support deep copying can cause the copy to be problematic if the object that contains the network structure is created at design time. ICloneable is also aware of the problem, as stated in its official definition: it supports both deep and shallow copies. A shallow copy is the creation of a new object that contains copies of all the member variables in the current object. If these member variables are reference types, the new object contains the same reference as the source object. A deep copy is a good copy of all the member variables, and the reference type is also recursively copied. For built-in types such as integral type, deep and shallow copies are the same result. Which of our types should be supported? This depends on the type itself. However, mixing deep and shallow copies in one type can lead to many inconsistent problems. Once you involve icloneable this problem, such mixed use is very difficult to release. Most of the time, we should completely avoid using icloneable to make the class simpler. This is much simpler to use and implement.

Any value type that is only a member of a built-in type does not have to support icloneable; It is much more efficient to copy all the values of a struct with a simple assignment statement than to Clone (). The Clone () method must be boxed for the return type in order to be coerced into a System.Object reference. The caller is also forced to retrieve the value from the box by force conversion. I know you have enough power to do this, but don't use the Clone () function to replace the assignment statement.

So what happens when a reference type is included in a value type? The most common scenario is that the value type contains a string:

public struct ErrorMessage
{
 private int errCode;
 private int details;
 private string msg;
// details elided
}

A string is a special case, because it is a constant class. If you specify an error message string, all error message classes are referenced to the same string. This does not cause any problems, which is not the same as other generic reference types. If you modify the MSG variable on any of the references, you will re-create a string object for it (see Principle 7).

(string is really an interesting class, many C + + programmers do not understand this class, there are some C # programs do not understand it, resulting in a lot of inefficiencies, or even error problems.) A good understanding of the class of string (and the relationship between string and Stringbulider) in C # is helpful for learning C # well. Because this idea of design can be used in our own type. )

In general, if a struct contains an arbitrary reference type, the situation in the copy is much more complicated. This is also rare, with built-in assignment statements that make a shallow copy of the structure, so that reference variables in two structures are referenced to the same object. If you want to make a deep copy, you must also copy the reference type, and also know if the reference type also supports a deep copy with Clone (). In either case, you don't have to add icloneable support to the value type, and the assignment statement creates a new copy of the value type.

A generalization value type: There is no reason to add support for a value type to the ICloneable interface! OK, now let's look at the reference type again. The reference type should support the ICloneable interface so that it is clear whether it supports deep or shallow copies. The sensible choice is to add support for icloneable, as it is clear that all derived classes must also support ICloneable. Look at the following simple inheritance relationship:

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" );
  }
}

Related Article

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.