0

このサイトには配列のサブセットを取得する方法を尋ねる質問がたくさんありますが、配列にbyte[].

byte[] bigTargetBytes = new byte[10000];

byte[] twentyBytes = sha256.ComputeHash(sourcebytes);  // size is 20 bytes, 
// how do I append this to the existing array without copying, using Linq, etc?

私がやりたくないのは、2つの配列を持ち、それらの間でコピーを行うことです。これは、配列の長さに比例して時間がかかるためです(そして私の配列は長いです)

4

2 に答える 2

2

どちらの方法でもコピーを作成する必要があります。Buffer.BlockCopy()最速の方法を使用することをお勧めします。

于 2012-12-17T21:09:09.677 に答える
1

あなたが何を望んでいるのかは明確ではありませんが、バイト配列に対する「ビュー」が必要だと思います。.Net 4.5 では、次の方法でこれを行うことができますArraySegment<T>

var a = new byte[100];
var s = new ArraySegment<Byte>(a, 9, 90);

((IList<Byte>)s)[0] = 10;
Console.WriteLine(a[9]);  // writes "10"

したがって、Write90Bytesメソッドは を返し、ArraySegment<Byte>それを基になる配列へのビューとして操作できます。これにより、コピーが回避されます。ただし、これArraySegment<T>は であることに注意してください。これはSystem.ValueType、これを にキャストするとIList<T>ボクシング ペナルティが発生することを意味します。

パフォーマンスが重要であり、コピーを避ける必要がある場合は、安全でないコンテキストでポインターを使用することも検討Write90Bytesできます。つまり、メソッドが aByte*を返し、その方法で配列にインデックスを付けることができます。

編集:あなたの編集を見たので、関数から配列のメモリ位置に値を返すことはできません。元の配列を引数として渡す必要があります。

編集2:あなたが求めていることはできません。このComputeHash関数は、それ自体が割り当てる配列を返します。必要なことを実行できる唯一の方法ComputeHashは、配列をパラメーターとして使用することです。検討:

// previously defined...
byte[] bigTargetBytes = new byte[10000];      

// This method doesn't really exist, but if it did it would look like this
sha256.ComputeHash(sourcebytes, bigTargetBytes, offset); 

.Net ではマネージド ランタイムであるため、メモリ割り当てに特定の制限がありますが、これはどのプログラミング言語でも共通のパターンです。C/C++ 開発では、書き込み先のオフセットと最大長を指定して事前に割り当てられた配列を渡すか、割り当てられたメモリを関数が返してから解放する責任が与えられるプロトコルが使用されます (フレームワークからコールバックされていない限り)。既存のバッファに値返すことはできません。

ただし、値によって割り当てられた GC 配列から 20 バイトをコピーするだけComputeHashの非常に簡単な操作であり、ランタイムが非常に効率的に処理することに注意してください。ときどきマイクロ秒レベルの一時停止に非常に敏感でない限り、実際のコピーと仮想の実装の違いに気付くことはありません。

于 2012-12-17T21:22:30.150 に答える