2

I have a Stream where I'd like to read data from (as value type segments) and move the position according to the size of the given type (declared as generics).

My current approach:

public byte ReadUInt8(Stream stream) {
    return (byte)stream.ReadByte();
}

public ushort ReadUInt16(Stream stream) {
    return (ushort)((ReadUInt8() << 8) | ReadUInt8());
}

...

What I'd like to achieve:

public TValue Read<TValue>(Stream stream)
    where TValue : struct
{
    var bufferSize    = Marshal.SizeOf(typeof(TValue));
    var buffer        = new byte[bufferSize];

    if(stream.Read(buffer, 0, bufferSize) == 0)
        throw new EndOfStreamException();

    return (TValue)buffer; // here's where I'm stuck

    // EDIT1: A possible way would be
    //        return (TValue)(object)buffer;
    //        but that feels like kicking puppies :/
}

Is this somehow possible? Are there any drawbacks from using Marshal.SizeOf() (performance-wise etc.)?

1 Answers1

1
return (TValue)buffer; // here's where I'm stuck

Yes, you have just shifted the problem. From not having a Stream.Read<T>() to not having a Convert<T>(byte[]) in the std library.
And you would have to call it like Read<int>() anyway so there isn't a direct advantage over BinaryReader.ReadInt32()

Now when you want to use it from another generic class/method, the Read<T>() syntax is useful but for the implementation you might as well map it to BinaryReader calls. I'm afraid that will require boxing:

obcject result = null;
if (typeof(TValue) == typeof(int))
  result = reader.ReadInt32();
else if (typeof(TValue) == typeof(double))
  result = reader.ReadDouble();
else ...

return (TValue) result;
H H
  • 263,252
  • 30
  • 330
  • 514
  • Yes, you have just shifted the problem. < How do I need to understand this? What kind of problem? And yes, the invocation will be done from a generic class. –  May 12 '15 at 21:30
  • You shifted it from no Read to no Convert in the library. – H H May 12 '15 at 21:34
  • Well there's the possibility to do `(T) Convert.ChangeType(value, typeof(T))` but I'm not quite sure in what kind of problems I might run with this. –  May 12 '15 at 21:38
  • **Edit** Just tried it out with an integer -> InvalidCastException :/ –  May 12 '15 at 21:44
  • Yes, a `byte[]` does not implement IConvertible. I think you're going to need the object and boxing, but maybe someone will post a better solution. – H H May 12 '15 at 21:55