Click here to Skip to main content
15,885,980 members
Please Sign up or sign in to vote.
0.00/5 (No votes)
See more:
I can't find any working way I've been searching for hours.

What I have tried:

public static T Clone<T>(T obj)
        {
            DataContractSerializer dcSer = new DataContractSerializer(obj.GetType());
            MemoryStream memoryStream = new MemoryStream();

            dcSer.WriteObject(memoryStream, obj);
            memoryStream.Position = 0;

            T newObject = (T)dcSer.ReadObject(memoryStream);
            return newObject;
        }




public static class ExtensionMethods
{
    // Deep clone
    public static T DeepClone<T>(this T a)
    {
        using (MemoryStream stream = new MemoryStream())
        {
            BinaryFormatter formatter = new BinaryFormatter();
            formatter.Serialize(stream, a);
            stream.Position = 0;
            return (T) formatter.Deserialize(stream);
        }
    }
}
which extends any class that's been marked as [Serializable] with a DeepClone method

MyClass copy = obj.DeepClone();
Posted
Updated 20-Sep-22 9:12am
Comments
Member 15627495 12-Sep-22 3:27am    
a class can't be copied.
an object can be copied.

class t A = new class t;class t B = A;
FierceLion 12-Sep-22 8:44am    
Sorry I didn't understand the sample code, would you please explain?
charles henington 17-Sep-22 12:00pm    
a class can be copied using the System.Runtime.Serialization.Formatters.Binary.BinaryFormatter class as the example shows above as long as the class is marked with the [System.Serializable] attribute. The example you provide simply passes one reference to another. With a deep copy like the example above you can save an instance of the class even when there's no reference to point to.
FierceLion 18-Sep-22 20:55pm    
This seems to have worked well for me, please submit it as an answer so I accept it:

The class must be marked with the [System.Serializable] attribute:



public static class Helper
{
public static T CreateDeepCopy<t>(T obj)
{
using (var ms = new MemoryStream())
{
IFormatter formatter = new BinaryFormatter();
formatter.Serialize(ms, obj);
ms.Seek(0, SeekOrigin.Begin);
return (T)formatter.Deserialize(ms);
}
}
}

From here: https://levelup.gitconnected.com/5-ways-to-clone-an-object-in-c-d1374ec28efa

Simply add
C#
[System.Serializable]
attribute to the class that you wish to Serialize.
Feel free to add these to your extensions
C#
public static byte[] Clone<T>(this T a)
        {
            using (MemoryStream stream = new MemoryStream())
            {
                BinaryFormatter formatter = new BinaryFormatter();
                formatter.Serialize(stream, a);
                return stream.ToArray();
            }
        }
        public static T FromClone<T>(this byte[] array)
        {
            using (MemoryStream stream = new MemoryStream(array))
            {
                BinaryFormatter formatter = new BinaryFormatter();
                return (T)formatter.Deserialize(stream);
            }
        }

Now you should be able to save the Clone and load an instance of cloned class from file.
As you wish sir.
public static class Helper { public static T CreateDeepCopy<t>(T obj) { using (var ms = new MemoryStream()) { IFormatter formatter = new BinaryFormatter(); formatter.Serialize(ms, obj); ms.Seek(0, SeekOrigin.Begin); return (T)formatter.Deserialize(ms); } } }
From here: https://levelup.gitconnected.com/5-ways-to-clone-an-object-in-c-d1374ec28efa

One thing that you will see using BinaryFormatter is that the output can get exceptionally large. I will provide 2 more helpers to help you compress them using System.IO.Compression

C#
public static byte[] CompressClone<T>(this T a)
        {
            byte[] clone = a.Clone<T>();
            using (var compressedStream = new MemoryStream())
            using (var zipStream = new GZipStream(compressedStream, CompressionMode.Compress))
            {
                zipStream.Write(clone, 0, clone.Length);
                zipStream.Close();
                return compressedStream.ToArray();
            }
        }
        public static T DecompressClone<T>(this byte[] array)
        {
            byte[] clone = null;
            using (var compressedStream = new MemoryStream(array))
            using (var zipStream = new GZipStream(compressedStream, CompressionMode.Decompress))
            using (var resultStream = new MemoryStream())
            {
                zipStream.CopyTo(resultStream);
                clone = resultStream.ToArray();
            }
            return clone.FromClone<T>();
        }
 
Share this answer
 
v6
Comments
FierceLion 20-Sep-22 15:21pm    
Please add the code that is in my comment to the question or the code in the link in the comment, so I accept the answer.
charles henington 20-Sep-22 16:18pm    
Also have used your example now as extension. public object DeepClone()
{
return this.DeepClone<Picture>();
}
public object Clone()
{
PictureData pictureData = new PictureData()
{
Colors = this.colors,
Format = this.format
};
return pictureData;
}
I have an interface tied to this class as well
public interface IDeepCloneable : ICloneable
{
object DeepClone();
}
BinaryFormatter is depreciated and in the latest release obsolete: Breaking change: BinaryFormatter serialization methods are obsolete and prohibited in ASP.NET apps - .NET | Microsoft Docs[^]

Have you seen this: 5 Ways to Clone An Object in C#[^] - I'd probably go with the XML version.
 
Share this answer
 
Comments
FierceLion 12-Sep-22 3:53am    
https://imgur.com/a/yWEPglN
FierceLion 12-Sep-22 10:32am    
First I had this error:
System.InvalidOperationException: 'DisksColorsFromTopAndSide.FormMain.oneTower cannot be serialized because it does not have a parameterless constructor.'

So I made a parameterless constructor, then I had this error:

System.InvalidOperationException: 'DisksColorsFromTopAndSide.FormMain.oneTower cannot be serialized because it does not have a parameterless constructor.'

So I made as public the class I want to duplicate.

Now it duplicates both the colors list and the int lists, the int list gets its values but the colors are all 0,0,0 in RGB but with the same number of elements as the main class object.

This content, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)



CodeProject, 20 Bay Street, 11th Floor Toronto, Ontario, Canada M5J 2N8 +1 (416) 849-8900