Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Serialization modifying contents of original object in C#

I have implemented a deep clone method using a copy constructor in C#. To verify that it works, I am testing it by comparing the results of serializing an object and it's clone. The serialization is done in terms of a generic object T. I have also tried it in terms of a concrete object and get the same results.

I have a method for serializing the objects into byte arrays

private byte[] ObjectToBytes(T obj)
{
    BinaryFormatter formatter = new BinaryFormatter();
    using (MemoryStream stream = new MemoryStream())
    {
        formatter.Serialize(stream, obj);
        stream.Seek(0, SeekOrigin.Begin);
        return stream.ToArray();
    }
}

The following code works fine.

T original = this.GetNewThing();
T clone = original.DeepClone();

// serialize after cloning
byte[] originalBytes = ObjectToBytes(original);
byte[] cloneBytes = ObjectToBytes(clone);

bool equal = true;
for (int i = 0; i < originalBytes.Length; i++)
{
    if(originalBytes[i] != cloneBytes[i]
    {
        equal = false;
        break;
    }
}
equal == true; // True!

However, when I switch the order of when the objects are serialized, the byte arrays are no longer equal.

// serialize before cloning
T original = this.GetNewThing();
byte[] originalBytes = ObjectToBytes(original);

T clone = original.DeepClone();
byte[] cloneBytes = ObjectToBytes(clone);

bool equal = true;
for (int i = 0; i < originalBytes.Length; i++)
{
    if(originalBytes[i] != cloneBytes[i]
    {
        equal = false;
        break;
    }
}
equal == true; // False!

Why does the order of serialization affect this? Does it have something to do with the BinaryFormatter or MemoryStream objects?

EDIT:

Here's what the deep clone method looks like

public MyClass DeepClone()
{
    return new MyClass(this);
}

and the constructor it uses looks like this

protected MyClass(MyClass myClass)
{
    if (myClass == null)
        throw new ArguementNullException("myclass");

    this.number = myClass.Number;
    this.number2 = myClass.Number2;
    this.number3 = myClass.Number3;
}

The object is by no means complex. All the values being copied are values types, so there are no reference types that need to be worried about.

like image 717
Danny Avatar asked May 13 '16 20:05

Danny


People also ask

What is serialization in C?

Serialization is the process of converting an object into a stream of bytes to store the object or transmit it to memory, a database, or a file. Its main purpose is to save the state of an object in order to be able to recreate it when needed. The reverse process is called deserialization.

What is Serializable attribute in c#?

This attribute is used in the class definition to indicate that a class can be serialized. By default, all fields in the class are serialized except for the fields that are marked with a NonSerializedAttribute . It is not necessary to use this attribute if a given type implements the System.


1 Answers

DeepClone, or something it calls in turn, seems to be changing the state of your source object.

like image 79
Slugart Avatar answered Oct 30 '22 22:10

Slugart