2

In my program I have a PacketFactory that builds buffers ready for sending over a NetworkStream. As you can see below this method takes a short as parameter. This short is passed to BitConverter.GetBytes.

internal static class PacketFactory
{
    internal static byte[] ToBuffer(PacketType type, short value)
    {
        byte[] packet = PacketTypeFactory.ToBuffer(type);
        byte[] valueBytes = BitConverter.GetBytes(value);

        byte[] buffer = new byte[packet.Length + valueBytes.Length];

        Array.Copy(packet, 0, buffer, 0, packet.Length);
        Array.Copy(valueBytes, 0, buffer, packet.Length, valueBytes.Length);

        return buffer;
    }
}

Now my problem: BitConverter.GetBytes has 10 overloads. I want to easily use all this overloads for my value parameter in the ToBuffer method.

Naive solution: Create all overloads that also exist on BitConverter.GetBytes and pass everything to an internal method. Is there a better way of solving this?

internal static class PacketFactory
{
    private static byte[] ToBuffer(PacketType type, byte[] value)
    {
        byte[] packet = PacketTypeFactory.ToBuffer(type);

        byte[] buffer = new byte[packet.Length + value.Length];

        Array.Copy(packet, 0, buffer, 0, packet.Length);
        Array.Copy(value, 0, buffer, packet.Length, value.Length);

        return buffer;
    }

    internal static byte[] ToBuffer(PacketType type, short value)
    {
        return ToBuffer(type, BitConverter.GetBytes(value));
    }
    internal static byte[] ToBuffer(PacketType type, int value)
    {
        return ToBuffer(type, BitConverter.GetBytes(value));
    }
}
Florian Harwoeck
  • 395
  • 2
  • 11

1 Answers1

2

Use a generic method that accepts a Func:

internal static byte[] ToBuffer<T>(SocketType type, Func<T, byte[]> getBytes, T value)
{
    byte[] packet = PacketTypeFactory.ToBuffer(type);
    byte[] valueBytes = getBytes(value);

    byte[] buffer = new byte[packet.Length + valueBytes.Length];

    Array.Copy(packet, 0, buffer, 0, packet.Length);
    Array.Copy(valueBytes, 0, buffer, packet.Length, valueBytes.Length);

    return buffer;
}

And call it like that:

short shortValue = 5;
PacketFactory.ToBuffer(SocketType.Raw, BitConverter.GetBytes, shortValue);
// BitConverter.GetBytes(short)

int intValue = 10;
PacketFactory.ToBuffer(SocketType.Raw, BitConverter.GetBytes, intValue);
// BitConverter.GetBytes(int)

This way, the correct overload of BitConverter.GetBytes will be passed to ToBuffer.

Kfir Guy
  • 2,545
  • 2
  • 14
  • 22
  • 1
    I'd say that it makes api harder to use. I would better create 10 overloads than force user of api to pass BitConverter.GetBytes every time. – Evk Mar 11 '17 at 17:53
  • 1
    Thx. This will work fine, but than I always need to pass `BitConverter.GetBytes`. It would be OK if I could move the Func at the end and use BitConverter.GetBytes as default value but that doesn't work, because default parameters must be compiletime constants. – Florian Harwoeck Mar 11 '17 at 17:58
  • This is the most elegant solution I can think of. The compiler must know the overload of `BitConverter.GetBytes`, so it must be used in the scope of the value. – Kfir Guy Mar 11 '17 at 18:01