using System.Collections.Generic;
using System.Diagnostics;
using System.ComponentModel;
using System.Globalization;
using Newtonsoft.Json.Converters;
public static class SerializationExtensions
static bool EnumTypeIsSigned(this Type tEnum)
var underlyingType = Enum.GetUnderlyingType(tEnum);
if (underlyingType == typeof(long) || underlyingType == typeof(int) || underlyingType == typeof(short) || underlyingType == typeof(sbyte))
if (underlyingType == typeof(ulong) || underlyingType == typeof(uint) || underlyingType == typeof(ushort) || underlyingType == typeof(byte))
throw new ArgumentException(tEnum.Name + " is not an enum type");
static bool IsSigned<TEnum>(this TEnum value) where TEnum : struct, IConvertible, IComparable, IFormattable
return typeof(TEnum).EnumTypeIsSigned();
public static void WriteEnum<TEnum>(this BinaryWriter writer, TEnum value) where TEnum : struct, IConvertible, IComparable, IFormattable
var underlyingValue = checked(value.ToInt64(NumberFormatInfo.InvariantInfo));
writer.Write(underlyingValue);
var underlyingValue = checked(value.ToUInt64(NumberFormatInfo.InvariantInfo));
writer.Write(underlyingValue);
public static TEnum ReadEnum<TEnum>(this BinaryReader reader) where TEnum : struct, IConvertible, IComparable, IFormattable
if (typeof(TEnum).EnumTypeIsSigned())
var underlyingValue = reader.ReadInt64();
return checked((TEnum)Enum.ToObject(typeof(TEnum), underlyingValue));
var underlyingValue = reader.ReadUInt64();
return checked((TEnum)Enum.ToObject(typeof(TEnum), underlyingValue));
public enum SByteEnum : sbyte
public enum ShortEnum : short
public enum IntEnum : int
public enum LongEnum : long
Fourteen = ((long)1 << 14),
ThirtyOne = ((long)1 << 31),
ThirtyTwo = ((long)1 << 32),
SixtyTwo = ((long)1 << 62),
SixtyThree = ((long)1 << 63),
public enum ByteEnum : byte
public enum UShortEnum : ushort
public enum UIntEnum : uint
Fourteen = ((uint)1 << 14),
ThirtyOne = ((uint)1 << 31),
public enum ULongEnum : ulong
Fourteen = ((ulong)1 << 14),
ThirtyOne = ((ulong)1 << 31),
ThirtyTwo = ((ulong)1 << 32),
ThirtyThree = ((ulong)1 << 33),
Sixty = ((ulong)1 << 60),
SixtyOne = ((ulong)1 << 61),
SixtyTwo = ((ulong)1 << 62),
SixtyThree = ((ulong)1 << 63),
public enum UnflaggedLongEnum : long
Fourteen = ((long)1 << 14),
ThirtyOne = ((long)1 << 31),
ThirtyTwo = ((long)1 << 32),
SixtyTwo = ((long)1 << 62),
SixtyThree = ((long)1 << 63),
public enum UnflaggedULongEnum : ulong
Fourteen = ((ulong)1 << 14),
ThirtyOne = ((ulong)1 << 31),
ThirtyTwo = ((ulong)1 << 32),
ThirtyThree = ((ulong)1 << 33),
Sixty = ((ulong)1 << 60),
SixtyOne = ((ulong)1 << 61),
SixtyTwo = ((ulong)1 << 62),
SixtyThree = ((ulong)1 << 63),
public enum CompositeExample : ulong
public static void Test()
List<Enum> values = new List<Enum>();
using (var ms = new MemoryStream())
using (var writer = new BinaryWriter(ms))
writer.WriteEnum(SByteEnum.Six);
values.Add(SByteEnum.Six);
writer.WriteEnum(ByteEnum.Six);
values.Add(ByteEnum.Six);
writer.WriteEnum(ShortEnum.Fourteen);
values.Add(ShortEnum.Fourteen);
writer.WriteEnum(UShortEnum.Fourteen);
values.Add(UShortEnum.Fourteen);
writer.WriteEnum(IntEnum.ThirtyOne);
values.Add(IntEnum.ThirtyOne);
writer.WriteEnum(UIntEnum.ThirtyOne);
values.Add(UIntEnum.ThirtyOne);
writer.WriteEnum(LongEnum.SixtyThree);
values.Add(LongEnum.SixtyThree);
writer.WriteEnum(ULongEnum.SixtyThree);
values.Add(ULongEnum.SixtyThree);
writer.WriteEnum(UnflaggedLongEnum.SixtyThree);
values.Add(UnflaggedLongEnum.SixtyThree);
writer.WriteEnum(UnflaggedULongEnum.SixtyThree);
values.Add(UnflaggedULongEnum.SixtyThree);
using (var ms = new MemoryStream(data))
using (var reader = new BinaryReader(ms))
TestRead<SByteEnum>(reader, values[count++]);
TestRead<ByteEnum>(reader, values[count++]);
TestRead<ShortEnum>(reader, values[count++]);
TestRead<UShortEnum>(reader, values[count++]);
TestRead<IntEnum>(reader, values[count++]);
TestRead<UIntEnum>(reader, values[count++]);
TestRead<LongEnum>(reader, values[count++]);
TestRead<ULongEnum>(reader, values[count++]);
TestRead<UnflaggedLongEnum>(reader, values[count++]);
TestRead<UnflaggedULongEnum>(reader, values[count++]);
Console.WriteLine("The following enums were serialized and deserialized successfully: ");
Console.WriteLine(JsonConvert.SerializeObject(values, new StringEnumConverter()));
static void TestRead<TEnum>(BinaryReader reader, Enum oldValue) where TEnum : struct, IConvertible, IComparable, IFormattable
var newValue = reader.ReadEnum<TEnum>();
if (!newValue.Equals(oldValue))
throw new InvalidOperationException("Incorrect deserialized values");
public static void Main()