2
\$\begingroup\$

I'm currently writing a binary reader that reads a value from a BinaryReader at a given position. For that I have to store the current position of the MemoryStream so I can restore it afterwards.

public byte GetByte(int position)
{
   long oldPosition = this.memoryStream.Position;
   this.memoryStream.Position = position;

   byte value = this.ReadByte();

   this.memoryStream.Position = oldPosition;

   return value;
}

EDIT: As requested, more similar functions:

public byte[] GetByteArray(int position, int length)
{
    long oldPosition = this.memoryStream.Position;
    this.memoryStream.Position = position;

    byte[] value = this.ReadByteArray(length);

    this.memoryStream.Position = oldPosition;

    return value;
}

public bool GetBoolean(int position)
{
    long oldPosition = this.memoryStream.Position;
    this.memoryStream.Position = position;

    bool value = this.ReadBoolean();

    this.memoryStream.Position = oldPosition;

    return value;
}

public ushort GetUInt16(int position)
{
    long oldPosition = this.memoryStream.Position;
    this.memoryStream.Position = position;

    ushort value = this.ReadUInt16();

    this.memoryStream.Position = oldPosition;

    return value;
}

and so on..

Is there any way to shorten this process and avoid doubled-code since I have many functions similar to that?

\$\endgroup\$
1
  • \$\begingroup\$ I'm conscious that neither your existing code, nor the code in Jesse's answer is thread-safe because of the use of Stream.Position. If you can be assured that it's only ever a MemoryStream that you'll be working with, you could produce a thread-safe implementation by working with the byte array (MemoryStream.GetBuffer()) and using BitConverter to read values. \$\endgroup\$
    – Snixtor
    Apr 15, 2016 at 0:06

1 Answer 1

3
\$\begingroup\$

Try a pair of methods like this:

public T GetValue<T>(int position, Func<T> readFunc)
{
    long oldPosition = this.memoryStream.Position;
    this.memoryStream.Position = position;

    T value = readFunc();

    this.memoryStream.Position = oldPosition;

    return value;
}

public T GetValue<T>(int position, Func<int, T> readFunc, int length)
{
    long oldPosition = this.memoryStream.Position;
    this.memoryStream.Position = position;

    T value = readFunc(length);

    this.memoryStream.Position = oldPosition;

    return value;
}

then they can be called as such:

byte b = GetValue(position, ReadByte);
byte[] ba = GetValue(position, ReadByteArray, length);
// etc.

ETA: I might write the methods like this to ensure the stream's position gets reset properly, even in the event of an exception:

public T GetValue<T>(int position, Func<T> readFunc)
{
    var oldPosition = this.memoryStream.Position;

    this.memoryStream.Position = position;
    try
    {
        return readFunc();
    }
    finally
    {
        this.memoryStream.Position = oldPosition;
    }
}

public T GetValue<T>(int position, Func<int, T> readFunc, int length)
{
    var oldPosition = this.memoryStream.Position;

    this.memoryStream.Position = position;
    try
    {
        return readFunc(length);
    }
    finally
    {
        this.memoryStream.Position = oldPosition;
    }
}
\$\endgroup\$
0

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.