2

バイトを操作するMemoryStreamand 関数があるとします。

現在のコードは次のようなものです。

void caller()
{
    MemoryStream ms = // not important
    func(ms.GetBuffer(), 0, (int)ms.Length);
}

void func(byte[] buffer, int offset, int length)
{
    // not important
}

変更はできませんfuncが、 内からストリーム データを変更する可能性を最小限に抑えたいと考えていfuncます。

ストリーム データが変更されないようにするには、どのようにコードを書き直すことができますか?

それとも、これはできませんか?

編集:

申し訳ありませんが、データのコピーを作成したくないということは言いませんでした。

4

5 に答える 5

5

コールし.ToArrayます。

func(ms.GetBuffer().ToArray(), 0, (int)ms.Length);

MSDNから(強調鉱山):

バッファーには、未使用の可能性がある割り当てられたバイトが含まれていることに注意してください。たとえば、文字列 "test" が MemoryStream オブジェクトに書き込まれた場合、GetBuffer から返されるバッファーの長さは 4 ではなく 256 で、252 バイトが未使用です。バッファー内のデータのみを取得するには、ToArray メソッドを使用します。ただし、ToArray はメモリ内にデータのコピーを作成します。


理想的にはfuncIEnumerable<byte>. メソッドが配列を取得すると、データを変更したくない場合は、メソッドがデータを変更しないと信頼できます。コントラクトを提供するIEnumerable<byte>場合、実装者は編集するコピーが必要かどうかを決定する必要があります。

于 2012-09-06T16:43:11.503 に答える
3

コピーを作成できず(他の回答で提案されているToArray)、関数の署名を変更できない場合は、func関数がデータを変更しなかったことを検証するだけです。

呼び出しの前後にある種のハッシュを計算し、それが同じかどうかを確認できます。func が基になるデータを (ハッシュの衝突により) 変更しなかったことを保証するものではありませんが、少なくともそれが起こったかどうかを知る良い機会を与えてくれます。非本番コードに役立つ場合があります...

本当の解決策は、信頼できないコードにデータのコピーを提供するか、データの変更を許可しないラッパー インターフェイス/オブジェクトを渡すことです (署名の変更/書き換えが必要ですfunc)。

于 2012-09-06T16:52:12.203 に答える
2

配列の「スライス」だけをメソッドに渡すことはできません。配列のコピーをメソッドに渡し、結果をコピーして戻します。

byte[] slice = new byte[length];
Buffer.BlockCopy(bytes, offset, slice, 0, length);
func(slice, 0, length);
Buffer.BlockCopy(slice, 0, bytes, offset, length);

または、メソッドを変更できる場合は、配列をラップし、各アクセスが許可された範囲内にあるかどうかをチェックするある種のプロキシ オブジェクトを渡します。

class ArrayView<T>
{
    private T[] array;
    private int offset;
    private int length;

    public T this[int index]
    {
        get
        {
            if (index < offset || index >= offset + length)
                throw new ArgumentOutOfRange("index");
            return array[index];
        }
        set
        {
            if (index < offset || index >= offset + length)
                throw new ArgumentOutOfRange("index");
            array[index] = value;
        }
    }
}
于 2012-09-06T16:47:22.067 に答える
2

を使用してストリームからデータをコピーしますms.ToArray()。明らかに、パフォーマンス ヒットが発生します。

于 2012-09-06T16:42:49.683 に答える
0

func()が実際にメモリ ストリームを変更できないことを確認しようとしていますか、それとも何か変更された場合にコードが例外をスローできれば十分ですか? 次のようなことをしたいようです:

void caller()
{
    MemoryStream ms = // not important
    var checksum = CalculateMyChecksum(ms);
    func(ms.GetBuffer(), 0, (int)ms.Length);
    if(checksum != CalculateMyChecksum(ms)){
        throw new Exception("Hey! Someone has been fiddling with my memory!");
    }
}

ただし、重要/重要なことにこれを推奨するのは気が進まないでしょう. もう少し情報をいただけますか?あなたの問題に対するより良い解決策と、この問題を完全に回避する方法があるかもしれません。

于 2012-09-06T17:27:45.013 に答える