title: C# Marshalling vs Serialization
body: <p>I have a C# app which read/write messages of some predefined protocol from/to USB.  So I have at least 2 options here. One is serialize/Deserialize. The other is marshal. At the beginning I was picking the first option and it worked fine. But after more and more message types are introduced I am annoyed by the cumbersome implementation for each message type and feel the marshal may be a better way to go. I haven't use marshal before. Is it the right way to go? I did some test. One problem I have is when I have a structure with an array, how to write to it? Such as the following:-</p>
  
  <pre><code>    [StructLayout(LayoutKind.Sequential, Size=TotalBytesInStruct),Serializable]
      public struct SomeData
      {
          /// char[15]
          [MarshalAsAttribute(UnmanagedType.ByValTStr, SizeConst = 15)]
          public sbyte[] data;
  
          /// int[15]
          [MarshalAsAttribute(UnmanagedType.ByValArray, SizeConst = 15)]
          public int[] prob;
      }
  </code></pre>
  
  <p>It appears that the data and prob are both reference and I have to new a object to use them, which sounds not quite right to me. I need the whole struct to be a continuous block of memory, which I don't think the new operator will do that for me.</p>
  
  <p>Any suggestion is really appreciated</p>
  
  <p>The following is how I did by serialization.</p>
  
  <pre><code>    List&lt;byte&gt; rawData = new List&lt;byte&gt;();
      rawData.AddRange(BitConverter.GetBytes(ProtocolVersion));
      // 16 bytes for operator ID
      byte[] temp = new byte[16];
      Array.Copy(Encoding.ASCII.GetBytes(OperatorId), temp, OperatorId.Length &gt; temp.Length ? temp.Length : OperatorId.Length);
      rawData.AddRange(temp);
  
      // 16 bytes for operator password
      Array.Clear(temp, 0, temp.Length);
      Array.Copy(Encoding.ASCII.GetBytes(OperatorPassword), temp, OperatorPassword.Length &gt; temp.Length ? temp.Length : OperatorPassword.Length);
      rawData.AddRange(temp);
  </code></pre>
  
  <p>The following is how I did by marshaling</p>
  
  <pre><code>    static byte[] RawSerialize&lt;T&gt;(T obj)
      {
          if (obj == null)
          {
              return null;
          }
  
          int size = Marshal.SizeOf(obj);
          byte[] result = new byte[size];
          IntPtr buffer = Marshal.AllocHGlobal(size);
          Marshal.StructureToPtr(obj, buffer, false);
          Marshal.Copy(buffer, result, 0, size);
  
          return result;
      }
  </code></pre>