开发者

does clone method in C# (or in java) use new operator internally?

This was a interview question actually, about different ways to create class instances. new and reflection are well known. But clon开发者_开发技巧e() also creates objects. But does it internally use new keyword to create it ? This was asked in context of c#, but would also like to know about java.


Clone() in C# is implemented by implementing the ICloneable interface. How you do this is entirely up to you.

For instance,

  • Immutable objects such as String and RuntimeType simply return this (i.e. themself).
  • A few standard Clone calls (i.e. System.Array, System.Delegate return Object.MemberwiseClone() which does a CLR call to create a shallow copy. I imagine this is similar to new() (it will create new references etc.) but I don't believe (though don't have the assembly to confirm) it will invoke a constructor.
  • Other objects tend to implement their own Clone() procedure.

Example Clone() method from System.Version

public object Clone()
{
    Version version = new Version();
    version._Major = this._Major;
    version._Minor = this._Minor;
    version._Build = this._Build;
    version._Revision = this._Revision;
    return version;
}


In Java, when calling clone() the convention is that the returned object should be obtained by calling super.clone(). Eventually, this gets to the Object's clone() method. At this point, the behavior is determined by the Clonable interface: if a class implements Clonable, the clone() method of Object returns a field-by-field copy of the object; otherwise a CloneNotSupportedException is thrown. So clone() creates an object without calling a constructor, what you get is a shallow copy of the object.

As a side note Java's clone is known to be broken and Joshua Bloch recommends to provides a copy constructor or copy factory instead. This is discussed in Effective Java 2nd Edition, Item 11: Override clone judiciously.


Typically, Clone implementations would use the protected MemberwiseClone method to create the base object, and then tweak fields as appropriate (for instance, deep copy a list instead of having both instances reference the same one).

There's nothing that says they have to do this, though - they could call a constructor to generate the object and then set fields as necessary.

Internally, MemberwiseClone is (I think - not sure on this) just a direct transcription of the memory the object occupies, and doesn't involve the constructor in any way.


For Java the answer is 'no'. Documentation is very specific about algorithm:

this method creates a new instance of the class of this object and initializes all its fields with exactly the contents of the corresponding fields of this object, as if by assignment; the contents of the fields are not themselves cloned. Thus, this method performs a "shallow copy" of this object, not a "deep copy" operation.

http://download.oracle.com/docs/cd/E17409_01/javase/6/docs/api/java/lang/Object.html#clone()

You can easily check it in practice also.


OK, so the consensus is, since new involves a constructor, and clone doesn't involve calling a constructor (unless we come up with our implementation of clone), clone doesn't use new internally.


For C# it is very easy to test what object.MemberwiseClone does in terms of constructors:

class Program
{
    class A : ICloneable
    {
        public int X = 2;
        public A()
        {
            Console.WriteLine("hiya");
            X = 1;
        }

        public object Clone()
        {
            A a = MemberwiseClone() as A;

            return a;
        }
    }

    static void Main(string[] args)
    {
        A a = new A();
        a.X = 3;
        A b = a.Clone() as A;
    }
}

Put a breakpoint in the constructor. It is called once for the above program. And if you think about it Clone in a base class cannot call a constructor:

  • What is it going to construct? It could reflect and get the most derived type.
  • But what if that type doesn't have a public parameterless constructor?
  • Can it invoke a private or protected constructor and expect the object to be initialized correctly.

The default implementation of MemberWiseClone has to depend on lower level type initialization and not construction. The alternative would be difficult to implement, difficult to understand and a source of hard to find bugs.

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜