私は現在、他のコードに基づいてコードを生成するプロジェクトに取り組んでいます。基本的に、プログラミング言語自体を DSL として使用します。
ジェネレーター ターゲットの 1 つは、バイナリ DataContractシリアライザーと、次のクラスの生成された ToBytes です。
[DataContract]
public partial class Root
{
[DataMember]
public int Number { get; set; }
[DataMember]
public Partial[] Partials { get; set; }
[DataMember]
public IList<ulong> Numbers { get; set; }
}
これになります:
public int Size
{
get
{
var size = 8;
// Add size for collections and strings
size += Partials.Sum(entry => entry.Size);
size += Numbers.Count * 8;
return size;
}
}
public byte[] ToBytes()
{
var index = 0;
var bytes = new byte[Size];
return ToBytes(bytes, ref index);
}
public byte[] ToBytes(byte[] bytes, ref int index)
{
// Convert Number
Buffer.BlockCopy(BitConverter.GetBytes(Number), 0, bytes, index, 4);;
index += 4;
// Convert Partials
// Two bytes length information for each dimension
Buffer.BlockCopy(BitConverter.GetBytes((ushort)(Partials == null ? 0 : Partials.Length)), 0, bytes, index, 2);
index += 2;
foreach(var value in Partials ?? Enumerable.Empty<Partial>())
{
value.ToBytes(bytes, ref index);
}
// Convert Numbers
// Two bytes length information for each dimension
Buffer.BlockCopy(BitConverter.GetBytes((ushort)(Numbers == null ? 0 : Numbers.Count)), 0, bytes, index, 2);
index += 2;
foreach(var value in Numbers ?? Enumerable.Empty<ulong>())
{
Buffer.BlockCopy(BitConverter.GetBytes(value), 0, bytes, index, 8);;
index += 8;
}
return bytes;
}
今でもこれは非常に高速です..のすべての使用を高速化する方法を探していますBuffer.BlockCopy(BitConverter.GetBytes
. byte[]
コンバージョンごとに新しいスモールを作成し、すでにbyte[]
ポジションを持っているときにそれをコピーするのは、依然としてリソースの無駄のようです。
コードを改善する最善の方法はありますか?
更新: @adrianm のコメントに基づいて、foreach を配列の for ループに置き換え、if ステートメントで null 許容型をラップします。別のスレッドのように構造体を使用することは望ましくありません。クラスと [DataContract] 属性を使用したいと思います。また、Linux 準拠のために、WinApi を使用できません。
Update2:生成されたコードの残りを追加しました。コメントのおかげで、将来のバージョンが含まれます
if (index + Size > bytes.Length)
// Some error handling