これがそれを行う1つの方法ですが、それが要件を満たすかどうかはわかりません. CPUエンディアンは重要ですか?
public struct ION
{
    public Single a0    ;
    public Single a1    ;
    public Single a2    ;
    public Single a3    ;
    public Single b0    ;
    public Single b1    ;
    public Single b2    ;
    public Single b3    ;
    public Double A1    ;
    public Double A0    ;
    public UInt32 Tot   ;
    public Int16  Wnt   ;
    public Int16  DtLS  ;
    public Int16  WnLSF ;
    public Int16  DN    ;
    public Int16  DtLSF ;
    public Int16  Wn    ;
    public UInt32 Tow   ;
    public Int16  bulwn ;
    public UInt32 bultow ;
    public UInt16 checksum
    {
        get
        {
            byte[][] raw =
            {
                BitConverter.GetBytes( a0     ) ,
                BitConverter.GetBytes( a1     ) ,
                BitConverter.GetBytes( a2     ) ,
                BitConverter.GetBytes( a3     ) ,
                BitConverter.GetBytes( b0     ) ,
                BitConverter.GetBytes( b1     ) ,
                BitConverter.GetBytes( b2     ) ,
                BitConverter.GetBytes( b3     ) ,
                BitConverter.GetBytes( A1     ) ,
                BitConverter.GetBytes( A0     ) ,
                BitConverter.GetBytes( Tot    ) ,
                BitConverter.GetBytes( Wnt    ) ,
                BitConverter.GetBytes( DtLS   ) ,
                BitConverter.GetBytes( WnLSF  ) ,
                BitConverter.GetBytes( DN     ) ,
                BitConverter.GetBytes( DtLSF  ) ,
                BitConverter.GetBytes( Wn     ) ,
                BitConverter.GetBytes( Tow    ) ,
                BitConverter.GetBytes( bulwn  ) ,
                BitConverter.GetBytes( bultow ) ,
            } ;
            byte[] cooked = raw.SelectMany( x => x ).ToArray() ;
            uint  accumulator = 0 ;
            for ( int i = 0 ; i < cooked.Length ; i+= 2 )
            {
                ushort value = BitConverter.ToUInt16( cooked , i ) ;
                accumulator += value ;
            }
            return (ushort) accumulator ;
        }
    }
}
または、安全でないコードにドロップダウンして、次のようにすることもできます。
public UInt16 checksum
{
  get
  {
    uint accumulator = 0 ;
    unsafe
    {
      fixed ( ION* x = &this )
      {
        for ( ushort *p = (ushort*) x ; p < x+1 ; ++p )
        {
          accumulator += *p ;
        }
      }
    }
    return (ushort) accumulator ;
  }
}
しかし、構造内または構造の最後にパディングがある場合、パディング オクテットがゼロになることが保証されているとは思えないため、結果に影響が生じる可能性があります。また、構造体に奇数のオクテットが含まれている場合、構造体の最後を超えて読み取ろうとして例外をスローする可能性があります...または間違った値を計算します。
もちろん、構造体をメモリ ストリームにシリアル化し、それを ushort のストリームとして読み取ることもできます。
public UInt16 checksum
{
  get
  {
    uint accumulator = 0 ;
    using ( BinaryReader reader = new BinaryReader( new MemoryStream() ) )
    {
      BinaryFormatter bf = new BinaryFormatter();
      bf.Serialize( reader.BaseStream , this ) ;
      reader.BaseStream.Seek(0,SeekOrigin.Begin) ;
      while ( reader.BaseStream.Position < reader.BaseStream.Length )
      {
        ushort value = reader.ReadUInt16() ;
        accumulator += value ;
      }
    }
    return (ushort) accumulator ;
  }
}
しかし、繰り返しになりますが、これはレイアウト、エンディアン、およびパディングに関する仮定です。また、構造体のサイズが奇数の場合は、ほぼ確実に例外をスローします。