public object Deserialize(byte[] data)
 {
     var flags = BitConverter.ToUInt16(data, 0);
     var ofs = sizeof(UInt16);
     var item = new CacheItem(flags, new ArraySegment<byte>(data, ofs, data.Length - ofs));
     return DeserializeInternal(item);
 }
        static object DeserializeInternal(CacheItem item)
        {
            if (item.Flags == RawDataFlag)
            {
                ArraySegment<byte> tmp = item.Data;

                if (tmp.Count == tmp.Array.Length)
                    return tmp.Array;

                // we should never arrive here, but it's better to be safe than sorry
                byte[] retval = new byte[tmp.Count];

                Array.Copy(tmp.Array, tmp.Offset, retval, 0, tmp.Count);

                return retval;
            }

            TypeCode code = (TypeCode)(item.Flags & 0x00ff);
			
            if (code == TypeCode.Empty)
                return null;

            byte[] data = item.Data.Array;
            int offset = item.Data.Offset;
            int count = item.Data.Count;

            switch (code)
            {
                case TypeCode.String:
                    return Encoding.UTF8.GetString(data, offset, count);

                case TypeCode.Boolean:
                    return BitConverter.ToBoolean(data, offset);

                case TypeCode.Int16:
                    return BitConverter.ToInt16(data, offset);

                case TypeCode.Int32:
                    return BitConverter.ToInt32(data, offset);

                case TypeCode.Int64:
                    return BitConverter.ToInt64(data, offset);
					
                case TypeCode.UInt16:
                    return BitConverter.ToUInt16(data, offset);

                case TypeCode.UInt32:
                    return BitConverter.ToUInt32(data, offset);

                case TypeCode.UInt64:
                    return BitConverter.ToUInt64(data, offset);

                case TypeCode.Char:
                    return BitConverter.ToChar(data, offset);

                case TypeCode.DateTime:
                    return DateTime.FromBinary(BitConverter.ToInt64(data, offset));

                case TypeCode.Double:
                    return BitConverter.ToDouble(data, offset);

                case TypeCode.Single:
                    return BitConverter.ToSingle(data, offset);

                case TypeCode.Object:
                    using (var ms = new MemoryStream(data, offset, count))
                    {
                        return new BinaryFormatter().Deserialize(ms);
                    }

                default: throw new InvalidOperationException("Unknown TypeCode was returned: " + code);
            }
        }