Hi,
Few days back I was trying to implement an algoritm. During the implementation I was interested to create a shallow copy of my class. In shallow copy the change in your cloned class will also reflect in the main object too. Shallow copy is the easiest way to clone your class. If you want that your class can be cloned then you can implement an interface called ICloneable.
Here I am giving a small example showing how to implement ICloneable interface. ICloneable interface expose only one method which is Clone.
Example:
First of all write a class, with two properties, like this:
public class myData
{
private string _Name;
public string Name
{
get { return _Name; }
set { _Name = value; }
}
private int _Age;
public int Age
{
get { return _Age; }
set { _Age = value; }
}
}
|
In the above code I wrote a class "myData". I declared two member variable which are _Name and _Age respectively. Then I wote two properties against these two member variables which are Name and Age respectively.
Now derive a class from List<T> and also implement IClonabale interface as shown in the following code.
class myCollectionofData<T> : List<T>,ICloneable
{
#region ICloneable Members
public object Clone()
{
return this.MemberwiseClone();
}
#endregion
}
|
In the above code I wrote a small class with the name "myCollectionofData". You can see that this class is implementing the ICloneable interface. As I mentioned earlier that this interface expose only one method which is Clone. I wrote only one line of code in this method which is "return this.MemberwiseClone();"
According to MSDN MemberwiseClone method creates a shallow copy by creating a new object, and then
copying the nonstatic fields of the current object to the new object.
If a field is a value type, a bit-by-bit copy of the field is
performed. If a field is a reference type, the reference is copied but
the referred object is not; therefore, the original object and its
clone refer to the same object.
Now all we need to do is to check our class. I wrote the following code to test my class:
class Program
{
static void Main(string[] args)
{
// Declare the object of the myData class
myData _myData = new myData();
_myData.Name = "Shahid Riaz Bhatti";
_myData.Age = 26;
myCollectionofData<myData> _myDataCollection = new myCollectionofData<myData>();
_myDataCollection.Add(_myData);
foreach (myData data in _myDataCollection)
{
Console.WriteLine(data.Name);
Console.WriteLine(data.Age);
}
myCollectionofData<myData> Cloned = (myCollectionofData<myData>)_myDataCollection.Clone();
foreach (myData data in Cloned)
{
Console.WriteLine(data.Name);
Console.WriteLine(data.Age);
}
}
}
|
In this class I declared the object of myData and set the Name and Age as follow:
// Declare the object of the myData class
myData _myData = new myData();
_myData.Name = "Shahid Riaz Bhatti";
_myData.Age = 26;
i.e. I set the Name to my name i.e. Shahid Riaz Bhatti :) and Age = 26.
Now I declared the object of myDataCollection class and add records in this object as follow:
myCollectionofData<myData> _myDataCollection = new myCollectionofData<myData>();
_myDataCollection.Add(_myData);
Now I Iterated this collection to see those records which we added in this collection. i.e.
foreach (myData data in _myDataCollection)
{
Console.WriteLine(data.Name);
Console.WriteLine(data.Age);
}
The above loop will give the following output:
Shahid Riaz Bhatti
26
Upto this point I didn't used the Clone method of my class. Now lets look at the following line of code:
myCollectionofData<myData> Cloned = (myCollectionofData<myData>)_myDataCollection.Clone();
In the above code I used the Clone method to get the cloned copy of my object. i.e.
_myDataCollection.Clone();
This will return me an Object. I unboxed that object into myCollectionofData<myData>. Now I need to check that did I get the copy of my object. For that purpose I Iterated the Cloned object and displayed the Name and Age as follow:
foreach (myData data in Cloned)
{
Console.WriteLine(data.Name);
Console.WriteLine(data.Age);
}
This will exactly give me the same output of the main object which is:
Shahid Riaz Bhatti
26
The complete code is given below:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace ConsoleApplication1
{
public class myData
{
private string _Name;
public string Name
{
get { return _Name; }
set { _Name = value; }
}
private int _Age;
public int Age
{
get { return _Age; }
set { _Age = value; }
}
}
class myCollectionofData<T> : List<T>,ICloneable
{
#region ICloneable Members
public object Clone()
{
return this.MemberwiseClone();
}
#endregion
}
class Program
{
static void Main(string[] args)
{
// Declare the object of the myData class
myData _myData = new myData();
_myData.Name = "Shahid Riaz Bhatti";
_myData.Age = 26;
myCollectionofData<myData> _myDataCollection = new myCollectionofData<myData>();
_myDataCollection.Add(_myData);
foreach (myData data in _myDataCollection)
{
Console.WriteLine(data.Name);
Console.WriteLine(data.Age);
}
myCollectionofData<myData> Cloned = (myCollectionofData<myData>)_myDataCollection.Clone();
foreach (myData data in Cloned)
{
Console.WriteLine(data.Name);
Console.WriteLine(data.Age);
}
}
}
}
|
Copy and paste the above code in a C# console application to see the output. If found any error on "using System.Linq;" then remove it coz I wrote this example in VS2008.
If u remembered that In the beginning of this article I stated that in shallow copy the change in your cloned class will also reflect in the main object too. Lets check this one too. For this I made a lil change in the code of the main program which is given below:
myCollectionofData<myData> Cloned = (myCollectionofData<myData>)_myDataCollection.Clone();
foreach (myData data in Cloned)
{
data.Name = "Name is Changed";
data.Age = "100";
} |
i.e. Instead of displaying the data of the cloned object, I changed it. i.e.
I changed Name to "Name is Changed" and Age from 26 to 100.
Now lets Iterate the main object to see its data as shown below:
foreach (myData data in _myDataCollection)
{
Console.WriteLine(data.Name);
Console.WriteLine(data.Age);
} |
Instead of displaying
Shahid Riaz Bhatti
20
It will display:
Name is Changed
100
The modified complete code of class Program is given below:
|
class Program
{
static void Main(string[] args)
{
// Declare the object of the myData class
myData _myData = new myData();
_myData.Name = "Shahid Riaz Bhatti";
_myData.Age = 26;
myCollectionofData<myData> _myDataCollection = new myCollectionofData<myData>();
_myDataCollection.Add(_myData);
foreach (myData data in _myDataCollection)
{
Console.WriteLine(data.Name);
Console.WriteLine(data.Age);
}
myCollectionofData<myData> Cloned = (myCollectionofData<myData>)_myDataCollection.Clone();
foreach (myData data in Cloned)
{
data.Name = "Name is Changed";
data.Age = "100";
}
foreach (myData data in _myDataCollection)
{
Console.WriteLine(data.Name);
Console.WriteLine(data.Age);
}
}
}
|
Note:
Clone method allows only the Shallow copy and not the deep copy. In shallow copy a change made in cloned object will also be reflected in the main object because in Shallow copy the orignal object and its clone refer to the same object. Deep copy is achieved by using the ISeralizable interface. i.e. First serialize the object, then deserialize back to a complete new copy. Now any changes in the new copy do not reflect on the orignal copy of the object.