Some developers believe that object cloning (creating new object which are copies of the original) is easier in C# than in other languages like C++. However, I do not agree with this. Somewhere I had read that a good language is one that places more hardship on framework (class) designers and less on client developers. This is where we find the principle getting violated.

C++

Lets consider a class that uses dynamically allocated memory and needs deep-copy when it is cloned. In the C++ world the developer of the class had to know things like copy-constructor and = operator overloading (and when they get called) to ensure that this happens correctly. A well-behaved class would look like

class MyClass
{
public:
MyClass()
// ctor

{

numListLen = 10;
numList =
new int[numListLen];
}
MyClass(
const MyClass& mc) // copy ctor
{
numListLen = mc.numListLen;
numList =
new int[numListLen];
for(int i = 0; i < numListLen; i++)
numList[i] = mc.numList[i];
}
MyClass&
operator=(const MyClass& mc)
{
if(this != &mc) // take care of mc = mc assignement
{
delete[] numList;
numList =
new int[numListLen];
for(int i = 0; i < numListLen; i++)
numList[i] = mc.numList[i];
}
return *this; // take care of mc1 = mc2 = mc3
}
virtual ~MyClass()
{
delete []numList;
}
int* numList;
int numListLen;
};

All this code just to ensure that copy happens as planned. So people call it complex. However, the client uses this class as.

MyClass mc1, mc2; // class Ctor
mc2 = mc1; // calls = operator overload
MyClass mc3 = mc1; // calls copy-ctor

mc1.numList[2] = 2;// mc2, mc3 are left untouched

So the client programmer simply need not care about shallow/deep copy. He assigns and creates object and all of the deep-copy stuff are handled under the hood.

C#

On C# you cannot overload the assignment operator and copy-ctor is not supported. The object cloning is supported using the ICloneable interface. Consider the following code that implements this interface

class MyClass : ICloneable
{
public MyClass()
{
deepRef =
new AnotherClass();
}
public object Clone() // ICloneable implementation
{
MyClass mc = this.MemberwiseClone() as MyClass;
mc.deepRef =
this.deepRef.Clone() as AnotherClass;
return mc;
}
public AnotherClass deepRef;
};

The code looks much simpler. However the catch is that the client writer needs to ensure that he never creates an object copy by direct assignment. So if he does the following there goes a bug into his code

MyClass mc1 = new MyClass();
MyClass mc2 = mc1; // Bug - shallow copy made

mc1.deepRef.x = 10;// and mc2.deepRef gets modified

So the client needs to call MyClass mc2 = mc1.Clone() as MyClass; to ensure deep copy. Since humans do forget bugs like this creep in.

Another issue is that ICloneable came in the pre-generic (read pre-historic) era. So its not type safe and you need ugly type-casting all over the code.

Ruby

ruby which was once a upon a time my favorite language sucks big time in deep-copy. You need to do something as below to get a deep copy

class Object
   def deepcopy
     Marshal::load(Marshal.dump(self))
   end
 end