2

How can I save my list<byte> to MemoryStream() without using ToArray() or creating new array ?

This is my current method:

public Packet(List<byte> data)
{
    // Create new stream from data buffer
    using (Stream stream = new MemoryStream(data.ToArray()))
    {
        using (BinaryReader reader = new BinaryReader(stream))
        {
            Length = reader.ReadInt16();
            pID = reader.ReadByte();
            Result = reader.ReadByte();
            Message = reader.ReadString();
            ID = reader.ReadInt32();
        }
    }
}
1
  • 2
    Why is this so bad? The answers posted give you alternatives but I doubt they are any more efficient Commented Aug 10, 2016 at 9:38

2 Answers 2

2

The ToArray solution is the most efficient solution possible using documented APIs. MemoryStream will not copy the array. It will just store it. So the only copy is in List<T>.ToArray().

If you want to avoid that copy you need to pry List<T> open using reflection and access the backing array. I advise against that.

Instead, use a collection that allows you to obtain the backing array using legal means. Write your own, or use a MemoryStream in the first place.

A List<T> is not the most efficient way to move around bytes anyway. Storing them is fine, moving them usually has more overhead. For example, adding items bytewise will be far slower than a memcpy.

Sign up to request clarification or add additional context in comments.

4 Comments

If possible, use a byte[] from the very beginning instead of List<byte>.
I was using byte[] , but i need dynamic arrays so list is more efficient than using array.resize multiple times.
@usr , thank you - this MemoryStream will not copy the array. It will just store it. answers to my question perfect.
@RoopeJärvenpää you can implement your own list that grows an array by a factor of two. That handles the growth and the idea to never copy the array contents.
0

What about something like:

public Packet(List<byte> data)
{
    using (Stream stream = new MemoryStream())
    {
        // Loop list and write out bytes
        foreach(byte b in data)
            stream.WriteByte(b);

        // Reset stream position ready for read
        stream.Seek(0, SeekOrigin.Begin);

        using (BinaryReader reader = new BinaryReader(stream))
        {
            Length = reader.ReadInt16();
            pID = reader.ReadByte();
            Result = reader.ReadByte();
            Message = reader.ReadString();
            ID = reader.ReadInt32();
        }
    }
}

But why do you have a list in the first place? Can't you pass it into the method as a byte[] to start with? It'd be interesting to see how you populate that list.

1 Comment

Well, i used Array.resize when i used byte[] to handle TCP packet streams. That caused my program to overwrite new array with previous arrays data - that could be fixed if i added thread sleep just after array creation. AND what i read on internet, they say list is most efficient way to have dynamic array. And that is what i need.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.