using System.Collections.Generic;
void Visit(IMessageVisitor v);
void Deserialize(BinaryReader r);
struct Message1 : IMessage
public void Visit(IMessageVisitor v) { v.Visit(ref this); }
public void Deserialize(BinaryReader r) { Float = r.ReadSingle(); }
struct Message2 : IMessage
public void Visit(IMessageVisitor v) { v.Visit(ref this); }
public void Deserialize(BinaryReader r) { UInt = r.ReadUInt32(); }
interface IMessageVisitor
void Visit(ref Message1 m);
void Visit(ref Message2 m);
class MessagePrinter : IMessageVisitor
public void Visit(ref Message1 m) { Console.WriteLine("Message1: {0}", m.Float); }
public void Visit(ref Message2 m) { Console.WriteLine("Message2: {0:x}", m.UInt); }
readonly Queue<uint> Queue = new Queue<uint>();
readonly IMessageSubQueue[] SubQueue = new IMessageSubQueue[] {
new MessageSubQueue<Message1>(),
new MessageSubQueue<Message2>(),
public int Count => Queue.Count;
public void QueueDeserialize(BinaryReader reader)
var count = reader.ReadUInt32();
for (uint i = 0; i < count; ++i)
var type = reader.ReadUInt32();
SubQueue[type].QueueDeserialize(reader);
public void Dequeue(IMessageVisitor v)
var type = Queue.Dequeue();
SubQueue[type].Dequeue(v);
interface IMessageSubQueue
void QueueDeserialize(BinaryReader reader);
void Dequeue(IMessageVisitor v);
class MessageSubQueue<M> : IMessageSubQueue where M : IMessage, new()
readonly Queue<M> Queue = new Queue<M>();
public void QueueDeserialize(BinaryReader reader)
public void Dequeue(IMessageVisitor v)
Queue.Dequeue().Visit(v);
static void Main(string[] args) {
var queue = new MessageQueue();
queue.QueueDeserialize(new BinaryReader(new MemoryStream(new byte[] {
0, 0, 0, 0, 0xDB, 0x0F, 0x49, 0x40,
var printer = new MessagePrinter();