C # clone an instance

Source: Internet
Author: User

Public ATM database deepclone () {memorystream MS = new memorystream (); binaryformatter BF = new binaryformatter (); BF. serialize (MS, this); Ms. position = 0; return BF. deserialize (MS) as ATM database ;}

C # supports two types: "value type" and "reference type ".

Value Type (such as char, Int, and float), enumeration type, and structure type. The reference type includes the class type, interface type, delegate type, and array type.

How to divide them? How they are allocated in computer memory

What is the difference between the value type and the reference type? 1. variables of the value type directly contain their data. 2. variables of the reference type store object references. For the reference type, two variables may reference the same object. Therefore, operations on one variable may affect the objects referenced by another variable. For value types, each variable has its own data copy, and operations on one variable cannot affect another variable.

Value types are implicitly inherited from system. valuetype. Therefore, a structure cannot be displayed to inherit a class. C # does not support multi-inheritance.

A stack is an advanced, FIFO data structure. In the memory, variables are allocated to the stack for operations. Heap is the memory area used to allocate space for Type instances (objects). It creates an object on the stack, it will pass the object address to the variable on the stack (in turn, it is called that the variable points to this object, or the variable references this object ).

Knowledge points on the design of object cloning

Shallow copy: It means to complicate all fields in the object to a new object's Value Type field. It simply copies a copy to the target object, changing the value of the Value Type field of the target object will not be reflected in the original object, because copying a copy of the referenced field means copying one of its references to the target object. Changing the value of the reference type field in the target object will be reflected in the original object, because copying is an address pointing to the heap

Deep copy: the processing of referenced fields is different from that of the shallow copy, deep copy creates a new object with the same (same content) fields in the original object. That is to say, this reference is different from the reference of the original object, when we change this field in the new object, it does not affect the content of the corresponding field in the original object.

Shallow replication: The memberwiseclone method of the object class must be used to create a superficial copy for deep replication: the clone method in the icloneable interface must be implemented, and the object to be cloned must be added with the [serializable] Feature

Class drawbase: system. Object, icloneable {

Public string name = "JMJ ";

Public drawbase (){}

Public object clone (){

Return this as object; // reference the same object

Return this. memberwiseclone (); // light copy

Return new drawbase () as object; // deep copy

}

}

Class program {

Static void main (string [] ARGs ){

Drawbase rect = new drawbase ();

Console. writeline (rect. Name );

Drawbase line = rect. Clone () as drawbase;

Line. Name = "a9fs3 ";

Console. writeline (rect. Name );

Drawbase ploy = line. Clone () as drawbase;

Ploy. Name = "LJ ";

Console. writeline (rect. Name );

Console. writeline (object. referenceequals (line, Ploy ));

Console. Readline ();

}

}

Running result: return this as object; // reference the same object

Output: JMJ a9fs3 LJ true

Return this. memberwiseclone (); // light copy

Return new drawbase () as object; // deep copy

Output values: JMJ false

Explanation: The return this as object method always references the same object, so the value on the corresponding heap memory will change! The last two methods are copying objects. The difference is that the replication type is different: Deep replication copies the entire filled object, including values of other reference types and value types of the object; the shortest copy only copies all references of an object. It copies without values and shares them with other objects that reference them.

Bytes --------------------------------------------------------------------------------------------------------

 

Although cloning is controversial in the real world, it is safe enough to use it in the. NET world, isn't it?

 

How many times do you implement the icloneable interface to implement a class, and write the sameCodeOr write specific code for each class.

In addition, when your class adds a new field, you will often forget to update the cloning method of this new field. If I'm not wrong, this will often lead to annoying bugs.

 

This is why my class exists. With the help of the reflection mechanism, I have created an abstract class that implements the icloneable interface with the default behavior.

Now you may be asking yourself: what is the default behavior? So I'm glad you asked. The default behavior of cloning is to use the following rules to clone every field in the class:

 

Check whether each field in the class supports the icloneable interface.

If a field does not support the icloneable interface, the field will be processed in the normal way.

This means that if the field is a value type, the value is copied. If the field is a reference type, the cloned field points to the same object.

If this field supports the icloneable interface, we will use its own clone method to clone it.

If this field supports the ienumerable interface, we need to check whether it supports the ilist or idictionary interface.

If yes, let's iterate over the set and check whether each item of the Set supports the icloneable interface.

How to Use

All you need to do to make your class support the icloneable interface is to inherit your class from the baseobject class described below:

 

Public class myclass: baseobject

{

Public String mystr = "test ";

Public int ID;

}

Public class mycontainer: baseobject

{

Public string name = "Test2 ";

Public myclass [] myarray = new myclass [5];

Public class mycontainer ()

{

For (INT I = 0; I <5; I ++)

{

This. myarray [I] = new myclass ();

}

}

}

 

Add the following code to the main method:

 

Static void main (string [] ARGs ){

Mycontainer con1 = new mycontainer ();

Mycontainer con2 = (mycontainer) con1.clone ();

Con2.myarray [0]. ID = 5;

}

When you monitor the con2 instance, you will see that the first item of the myclass instance has changed to 5, but the con1 instance has not changed.

In this way, you will understand that any field added to the class that supports the icloneable interface will be cloned in the same way.

In addition, if this field supports the ilist or idictionary interface, the clone method detects this field, polls all items, and tries to clone them.

Implementation

/// <Summary>
/// The baseobject class is an abstract class used for inheritance.
/// Each class inherited from this class automatically supports the clone method.
/// This class implements the icloneable interface, and each object inherited from this object will
/// Supports the icloneable interface.
/// </Summary>
Public abstract class baseobject: icloneable
{
/// <Summary>
/// Clone the object and return a reference to the cloned object
/// </Summary>
/// <Returns> reference A New Clone object </returns>
Public object clone ()
{
// First, create an instance of the specified type
Object newobject = activator. createinstance (this. GetType ());
// Obtain the field array of the New Type instance.
Fieldinfo [] fields = newobject. GetType (). getfields ();
Int I = 0;
Foreach (fieldinfo fi in this. GetType (). getfields ())
{
// Determine whether the field supports the icloneable interface.
Type iclonetype = Fi. fieldtype.
Getinterface ("icloneable", true );
If (iclonetype! = NULL)
{
// Obtain the icloneable interface of the object.
Icloneable iclone = (icloneable) Fi. getvalue (this );
// We use the clone method to set a new value for the field.
Fields [I]. setvalue (newobject, iclone. Clone ());
}
Else
{
// If this field supports the icloneable interface, set it directly.
Fields [I]. setvalue (newobject, Fi. getvalue (this ));
}
// Check whether the object supports the ienumerable interface. If yes,
// We also need to enumerate all its items and check whether they support the ilist or idictionary interface.
Type ienumerabletype = Fi. fieldtype. getinterface ("ienumerable", true );
If (ienumerabletype! = NULL)
{
// Obtain the ienumerable interface of this field
Ienumerable ienum = (ienumerable) Fi. getvalue (this );
// This version supports the ilist or idictionary interface to iterate the set.
Type ilisttype = Fields [I]. fieldtype. getinterface ("ilist", true );
Type idictype = Fields [I]. fieldtype. getinterface ("idictionary", true );
Int J = 0;
If (ilisttype! = NULL)
{
// Obtain the ilist interface.
Ilist list = (ilist) fields [I]. getvalue (newobject );
Foreach (Object OBJ in ienum)
{
// Check whether the current item supports the icloneable interface.
Iclonetype = obj. GetType ().
Getinterface ("icloneable", true );
If (iclonetype! = NULL)
{
// If the icloneable interface is supported,
// We use it to set the object clone in the list.
Icloneable clone = (icloneable) OBJ;
List [J] = clone. Clone ();
}
// Note: if the items in the list do not support the icloneable interface
// Items in the clone list will be the same as those in the original list
// (As long as this type is a reference type)
J ++;
}
}
Else if (idictype! = NULL)
{
// Obtain the idictionary Interface
Idictionary DIC = (idictionary) fields [I].
Getvalue (newobject );
J = 0;
Foreach (dictionaryentry de in ienum)
{
// Check whether the current item supports the icloneable interface.
Iclonetype = de. value. GetType ().
Getinterface ("icloneable", true );
If (iclonetype! = NULL)
{
Icloneable clone = (icloneable) De. value;
Dic [de. Key] = clone. Clone ();
}
J ++;
}
}
}
I ++;
}
Return newobject;
}
}

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.