title: Efficiently convert byte array to Decimal
body: <p>If I have a byte array and want to convert a contiguous 16 byte block of that array, containing .net's representation of a <code>Decimal</code>, into a proper <code>Decimal</code> struct, what is the most efficient way to do it?</p>
  
  <p>Here's the code that showed up in my profiler as the biggest CPU consumer in a case that I'm optimizing.</p>
  
  <pre><code>public static decimal ByteArrayToDecimal(byte[] src, int offset)
  {
      using (MemoryStream stream = new MemoryStream(src))
      {
          stream.Position = offset;
          using (BinaryReader reader = new BinaryReader(stream))
              return reader.ReadDecimal();
      }
  }
  </code></pre>
  
  <p>To get rid of <code>MemoryStream</code> and <code>BinaryReader</code>, I thought feeding an array of <code>BitConverter.ToInt32(src, offset + x)</code>s into the <code>Decimal(Int32[])</code> constructor would be faster than the solution I present below, but the version below is, strangely enough, twice as fast.</p>
  
  <pre><code>const byte DecimalSignBit = 128;
  public static decimal ByteArrayToDecimal(byte[] src, int offset)
  {
      return new decimal(
          BitConverter.ToInt32(src, offset),
          BitConverter.ToInt32(src, offset + 4),
          BitConverter.ToInt32(src, offset + 8),
          src[offset + 15] == DecimalSignBit,
          src[offset + 14]);
  }
  </code></pre>
  
  <p>This is <strong>10 times as fast</strong> as the <code>MemoryStream/BinaryReader</code> combo, and I tested it with a bunch of extreme values to make sure it works, but the decimal representation is not as straightforward as that of other primitive types, so I'm not yet convinced it works for 100% of the possible decimal values.</p>
  
  <p>In theory however, there could be a way to copy those 16 contiguous byte to some other place in memory and declare that to be a Decimal, without any checks. Is anyone aware of a method to do this?</p>
  
  <p>(There's only one problem: Although decimals are represented as 16 bytes, some of the possible values do not constitute valid decimals, so doing an unchecked<code>memcpy</code> could potentially break things...)</p>
  
  <p>Or is there any other faster way?</p>