1

I've been trying to write a Buffer class that lets me write to and read from an internal List buffer using generic methods. In C++ it was no problem, since we have nice access to the memory directly (memcpy (I know memcpy is unsafe) and so on).

I have tried the following:

// private readonly List<byte> _buffer = new List<byte>();
public void Write<T>(T value) where T : byte, short, ushort, int, uint {
    _buffer.AddRange(BitConverter.GetBytes(value));
}

... But it says, that the best overload has some invalid arguments (value).

I also have problems reading a value of the type byte, short, ushort, int or uint. I could surely determine the type of T and then use the BitConverter class to convert the bytes but i'm sure there is a more easy and DRY way to do this (which I haven't discovered yet).

How to implement such methods to keep the class sweet and simple?

EDIT:

To read from the buffer I've tried the following:

public T Read<T>(bool moveIndex = true) {
    T data = default(T);
    var size = Marshal.SizeOf(data);
    IntPtr ptr = Marshal.AllocHGlobal(size);
    Marshal.PtrToStructure(ptr, data);
    Marshal.Copy(_buffer.ToArray(), _readIndex, ptr, size);
    Marshal.FreeHGlobal(ptr);
    if (moveIndex) {
        _readIndex += size;
    }
    return data;
}

But it throws me a System.ArgumentException in this line Marshal.PtrToStructure(ptr, data);

lenny.myr
  • 903
  • 2
  • 11
  • 20
  • 1
    I'm afraid the generic approach probably won't be possible in C#. C++ templates and C# generics just don't work in the same way! This approach should work for you though: http://stackoverflow.com/a/3278908/2609288 – Baldrick Aug 26 '14 at 04:39
  • Hi @Baldrick, your link doesn't help me that much, as I want to write simple datatypes like int or short to the buffer, not a structure. – lenny.myr Aug 26 '14 at 17:22
  • Make an array of length 1, then use `Buffer.BlockCopy`? – Ben Voigt Aug 26 '14 at 19:53

1 Answers1

0

Would something like this suit your needs?

public void Write<T>(T value) where T: struct
{
    int size = Marshal.SizeOf(value);
    var bytes = new byte[size];
    IntPtr ptr = Marshal.AllocHGlobal(size);
    Marshal.StructureToPtr(value, ptr, true);
    Marshal.Copy(ptr, bytes, 0, size);
    Marshal.FreeHGlobal(ptr);
    _buffer.AddRange(bytes);
}
Kyle
  • 1,366
  • 2
  • 16
  • 28
  • Hi @Kyle, your code works for me. I tried to do the same for reading from that buffer but how do I figure out the size of type T? Marshal.SizeOf() expects a variable, not a type. – lenny.myr Aug 26 '14 at 17:21