Here's one way to do it, but whether that will meet the requirements...who knows. Does cpu endianness matter?
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 ;
}
}
}
or you could drop down to unsafe code and do something like:
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 ;
}
}
But if there's any padding in the structure or at the end of the structure, I don't believe you're guaranteed that padding octets are zeroed, so your results might be impacted. And if your structure contains an odd number of octets, you're likely to throw an exception trying to read past the end of the struct...or compute an incorrect value.
And of course, you could serialize the struct to a memory stream and then read that as a stream of ushorts:
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 ;
}
}
But again, that's making assumptions about layout and endianness and padding. And you'll almost certainly throw and exception if the structure size is odd.