# DRY 0-bandwidth-overhead-serialization in C#: virtual, delegates or reflection? [closed]

I'm (de)serializing some datastructures for a network-multiplayer game, and for each datastructure that's to be (de)serialized, I want to define the order of (de)serialization only once for maintainability without any additional bandwidth overhead, and as little performance cost and extra typing as possible.

I can use C#'s abstract class methods to achieve my goal, but there's several problems with doing so:

1. performance: adding an additional abstract method call to each (de)serialization operation isn't ideal

2. extra typing: I have to needlessly initialize all variables I'm deserializing because C# won't allow me to pass "ref" and "out" parameters interchangeably

How can I avoid duplicating the definition of a datastructure's (de)serialization while also avoiding some or all of the above issues, and continuing to avoid any additional bandwidth cost?

(ProtoBufs and BinaryFormatter both seem to use some additional bandwidth for metadata to describe the "payload" data, and XmlSerializer, DataContractSerializer and NetDataContractSerializer are all xml based and therefore more bandwidth intensive than a straight binary serialization. I also toyed with delegates and reflection, but this solution came to me most readily):

public struct ControllerSnapshot
{
public Vector2 m_lStick;

static private void Op(ref float lStickX, ref float lStickY, Op<float> op)
{
//define (de)serialization order here once and only once
lStickX = op.Invoke(lStickX);
lStickY = op.Invoke(lStickY);
}
{
float lStickX,lStickY;
lStickX = lStickY = 0.0f;//2.can't use "out"; have to match Op's "ref" params

m_lStick = new Vector2(lStickX,lStickY);
}
{
OpWrite<float> opWrite = new OpWrite<float>(bitStream);
Op(ref m_lStick.x, ref m_lStick.y, opWrite);
}
};

//in order to make the above work this needs to be defined:
abstract class Op<T>
{
{
m_bitStream = bitStream;
}
abstract public T Invoke(T arg);

}
{
override public T Invoke(T arg)
{
}
}
class OpWrite<T>:Op<T>
{
public OpWrite(uLink.BitStream bitStream) : base(bitStream) { }
override public T Invoke(T arg)
{
m_bitStream.Write<T>(arg);
return arg;
}
}

//by contrast, the "obvious" code duplicates the order of (de)serialization, which I
//want to avoid, especially as (de)serialization becomes increasingly complex:
{
float lStickX,lStickY;

m_lStick = new Vector2(lStickX,lStickY);
}
{
bitStream.Write<float>(m_lStick.x);
bitStream.Write<float>(m_lStick.y);
}


## closed as off-topic by Josh♦Dec 2 '13 at 17:45

This question appears to be off-topic. The users who voted to close gave this specific reason:

• "Programming questions that aren't specific to game development are off-topic here, but can be asked on Stack Overflow. A good rule of thumb is to ask yourself "would a professional game developer give me a better/different/more specific answer to this question than other programmers?"" – Josh
If this question can be reworded to fit the rules in the help center, please edit the question.

• fwhoa, this is a really long question. – Shotgun Ninja Apr 24 '13 at 21:07
• ProtoBufs uses no additional metadata unless you actually need it for something. Using the .proto IDL files can help reduce redundancy and make bad (for serialization) class designs easier to spot. – Sean Middleditch Apr 24 '13 at 21:44
• Are long questions automatically bad? I think I expressed all the relevant information pretty concisely -- how else could I get the problem across concretely? – Nathan Frost Apr 24 '13 at 23:04
• @Philipp Don't be so sure - game networking has some fairly specific requirements and differences, compared to other kinds of serialization. – Andrew Russell Apr 25 '13 at 11:04
• @Philipp: The question was originally posed on stackoverflow with the "no additional bandwidth" requirement omitted -- some programmers gave me some good solutions that all seemed to increase bandwidth, so I thought gamedev might be more performance-conscious. – Nathan Frost Apr 25 '13 at 19:12