これがそれを行う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 ;
}
}
しかし、繰り返しになりますが、これはレイアウト、エンディアン、およびパディングに関する仮定です。また、構造体のサイズが奇数の場合は、ほぼ確実に例外をスローします。