copy a class, C#

后端 未结 12 1759
失恋的感觉
失恋的感觉 2020-12-03 10:13

Is there a way to copy a class in C#? Something like var dupe = MyClass(original).

相关标签:
12条回答
  • 2020-12-03 10:50

    One possibility is to clone it. You have to implement the interface ICloneable and the Clone method.

    0 讨论(0)
  • 2020-12-03 10:55

    Yes and no. This is an area where you need to be a bit careful because there are some traps (and then again, it's not difficult).

    First of all, if you poke around in the Base Class Library (BCL) a bit, you may discover the ICloneable interface. Not all types implement this interface, but those that do have a Clone method that will return a new instance of the same type with (presumably) the same values.

    However, herein lies a trap: The ICloneable interface does not sufficiently specify whether a deep clone or a shallow clone is expected, so some implementations do one thing, and other implementations the other. For this reason, ICloneable isn't used much, and its further use is actively being discouraged - see the excellent Framework Design Guidelines for more details.

    If you dig further into the BCL, you may discover that System.Object has the protected MemberwiseClone method. While you can't call this method directly from another type, you can use this method to implement cloning in your own objects.

    A common cloning pattern is to define a protected constructor of the class you want to clone and pass an already existing instance as a parameter. Something like this:

    public class MyClass()
    {
        public MyClass() {}
    
        protected MyClass(MyClass other)
        {
            // Cloning code goes here...
        }
    
        public MyClass Clone()
        {
            return new MyClass(this);
        }
    }
    

    However, that obviously only works if you control the type you wish to clone.

    If you wish to clone a type that you can't modify, and which doesn't provide a Clone method, you will need to write code to explicitly copy each piece of data from the old instance to the new instance.

    0 讨论(0)
  • 2020-12-03 10:59

    I think the author is asking about copy constructors...

    The answer is "yes, but only if you implement it yourself", there's no 'automatic' way of doing it without some heavy cludges (reads: Reflection):

    class MyClass {
        private string _name;
    
        // standard constructor, so that we can make MyClass's without troubles
        public MyClass(string name) {_name = name}
        public MyClass(MyClass old) {
            _name = old._name;
            // etc...
        }
    }
    

    The other thing of note in this respect is the IClonable interface, and the .Clone() method this provides. Also .MemberwiseClone() protected method provided by the Object class can help implementing both these methods.

    0 讨论(0)
  • 2020-12-03 10:59

    An easy way to clone an object is writing it into a stream and read it again:

    public object Clone()
    {
        object clonedObject = null;
        BinaryFormatter formatter = new BinaryFormatter();
        using (Stream stream = new MemoryStream())
        {
            formatter.Serialize(stream, this);
            stream.Seek(0, SeekOrigin.Begin);
            clonedObject = formatter.Deserialize(stream);
        }
    
        return clonedObject;
    }
    

    But be aware of, that this can cause problems with so called aggregate object.

    0 讨论(0)
  • 2020-12-03 10:59

    Do you mean a copy constructor, like it exists in C++ ?

    It does not exists in C#. What you can do, is write your own (which is tedious), or you can write a 'Clone' method which uses serialization to create a new instance which has exactly the same values as the original class.

    You can serialize the current instance, deserialize it, and return the deserialized result. Disadvantage is that your class has to be Serializable.

    0 讨论(0)
  • 2020-12-03 11:01

    You are probably talking about a deep copy (deep copy vs shallow copy)?

    You either have to:

    1. implement (hard code) a method of your own,
    2. try to implement (or find) an implementation that uses Reflection or Emit to do it dynamically (explained here),
    3. use serialization and deserialization to create a deep copy, if the object is marked with a [Serializable] attribute.
    public static T DeepCopy<T>(T other)
    {
        using (MemoryStream ms = new MemoryStream())
        {
            BinaryFormatter formatter = new BinaryFormatter();
            formatter.Serialize(ms, other);
            ms.Position = 0;
            return (T)formatter.Deserialize(ms);
        }
    }
    

    To get a shallow copy, you can use the Object.MemberwiseClone() method, but it is a protected method, which means you can only use it from inside the class.

    With all the deep copy methods, it is important to consider any references to other objects, or circular references which may result in creating a deeper copy than what you wanted.

    0 讨论(0)
提交回复
热议问题