Academic Integrity: tutoring, explanations, and feedback — we don’t complete graded work or submit on a student’s behalf.

Say I have a class workStockItem, that I wish to serialize. Which is the better

ID: 644476 • Letter: S

Question

Say I have a class workStockItem, that I wish to serialize.

Which is the better style?

using a static method

or

using a non-static method (maybe even implemented as a property as seen below)
Example implementations:

internal static byte[] serialiaze(workStockItem toSer)
    {
        IFormatter formatter = new BinaryFormatter();
        MemoryStream stream = new MemoryStream();
        formatter.Serialize(stream, toSer);
        return stream.ToArray();
    }

internal byte[] binaryRepresentation
    {
        get
        {
            IFormatter formatter = new BinaryFormatter();
            MemoryStream stream = new MemoryStream();
            formatter.Serialize(stream, this);
            return stream.ToArray();
        }
    }
Again:
Which is better style and why?

Explanation / Answer

tl;dr

I suggest static methods, or even instance methods can be alright depending on the objects you're working with and how long lived they are as well as how stateful they are.

Do not use properties for this. Properties should be as idempotent as possible (repeated access should return the same result constantly). If A property needs to execute logic to divine its state, that's not always terrible, but properties should never be changing state on a Get.

Usually when you're dealing with an underlying set of data to deserialize something you'll have a current position in that set, and the act of deserializing will move that position thus causing a Get to change state.

I once wrote a bunch of binary serialization for some simple objects we had, and found it quite helpful to just make the methods extension methods on the BinaryReader and BinaryWriter classes. If you look at these classes, they already have methods for turning binary data into data types with ReadInt and ReadString etc, so the static methods relied on these to reconstruct the objects.

It as as such:

public class FunnyAnimal
{
public int NumberOfLegs { get; set; }
public string Name { get; set; }
public Tuple<int, int> EarHearingSensitivity { get; set; }
}

public static class BinaryWriterExtensions
{
public FunnyAnimal WriteFunnyAnimal(this BinaryWriter writer, FunnyAnimal animalToBeWritten)
{
writer.WriteInt(animalToBeWritten.NumberOfLegs);
writer.WrinteString(animalToBeWritten.Name);
writer.WriteInt(animalToBeWritten.EarHearingSensitivity.Item1);
writer.WriteInt(animalToBeWritten.EarHearingSensitivity.Item2);
}
}

public static class BinaryReaderExtensions
{
public FunnyAnimal ReadFunnyAnimal(this BinaryReader reader)
{
return new FunnyAnimal()
{
NumberOfLegs = reader.ReadInt(),
Name = reader.ReadString(),
EarHearingSensitivity = Tuple.Create(reader.ReadInt(), reader.ReadInt())
};
}
}
Then the use is:

//To write it out to a stream
using (var writer = new BinaryWriter(someUnderlyingStreamToWriteTo))
{
writer.WriteFunnyAnimal(yourFunnyAnimalObject);
}

//To read it in from a stream
FunnyAnimal deserializedFunnyAnimal = null;
using (var reader = new BinaryReader(someUnderlyingStreamToReadFrom))
{
deserializedFunnyAnimal = reader.ReadFunnyAnimal();
}
The same approach could be applied to any type of serializer you're working with, if you're just using straight BinaryFormatter you can make your extensions on a MemoryStream and make the methods utilize a BinaryFormatter to read and write from the stream, but the use is then clear and simple, construct a MemoryStream and ReadFunnyAnimal or WriteFunnyAnimal on it, and the extension methods will create and operate the BinaryFormatter

Last thoughts

When dealing with binary serialization/deserialization you'll find the most convenient stream underlying a lot of times may just be a MemoryStream with an array backing it so you can just grab the byte array when you're done, unless you have a file or other resource you're specifically serializing across.

If you have complex objects inside that need serializing, this technique is helpful because the implementation for the writer and reader extensions will have access to the reader/writer so the extension methods for your embedded complex objects will also be in scope to be used as:

return new FunnyAnimal() { ComplexTailMember = reader.ReadTail(); }
Additionally it's worth recognizing when dealing with serialization/deserialization implementations who's going to own the stream. Your extensions shouldn't own it in a sense that they should not open/move/dispose of it after they're done, rather that should be on the ownus of the code that creates the reader/writer, so rule of thumb dealing with streams and streamreader/writers:

If your Stream/StreamReader/StreamWriter are parameters to your method, you should not dispose of them. If you create the Stream it's your responsibility to dispose of it.

The one sniglet to be careful of there is sometimes a StreamReader/StreamWriter's dispose method will dispose of the underlying stream, just beware that you don't therefore dispose of your reader/writer before you are completely finished with your stream.

Hire Me For All Your Tutoring Needs
Integrity-first tutoring: clear explanations, guidance, and feedback.
Drop an Email at
drjack9650@gmail.com
Chat Now And Get Quote