C# 安全访问MemoryStream中的数据

C# 安全访问MemoryStream中的数据,c#,bytearray,memorystream,C#,Bytearray,Memorystream,假设我有一个MemoryStream和对字节进行操作的函数 当前代码如下所示: 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中更改流数据的可能

假设我有一个
MemoryStream
和对字节进行操作的函数

当前代码如下所示:

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
中更改流数据的可能性

我如何/应该重写代码以确保流数据不会更改

或者这不能做到

编辑:


很抱歉,我没有提到a我不想复制数据。

使用
ms.ToArray()从流中复制数据。
。显然,性能会受到影响。

调用
。ToArray

func(ms.GetBuffer().ToArray(), 0, (int)ms.Length);
来自(我的):

请注意,缓冲区包含可能未使用的已分配字节。 例如,如果字符串“test”被写入MemoryStream中 对象,则从GetBuffer返回的缓冲区长度为256,而不是 4,其中252个字节未使用要仅获取缓冲区中的数据,请使用 ToArray方法;但是,ToArray会在中创建数据的副本 内存。



理想情况下,您可以将
func
更改为使用
IEnumerable
。一旦一个方法拥有了数组,你就相信如果你不希望他们修改数据,他们不会修改数据。如果契约提供的是
IEnumerable
,则实现者必须决定是否需要一个副本进行编辑。

不能仅将数组的“切片”传递给方法。将数组的副本传递给方法并将结果复制回:

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;
        }
    }
}
类阵列视图
{
私有T[]数组;
私有整数偏移;
私有整数长度;
公共T此[int索引]
{
得到
{
如果(索引<偏移量| |索引>=偏移量+长度)
抛出新的ArgumentOutOfRange(“索引”);
返回数组[索引];
}
设置
{
如果(索引<偏移量| |索引>=偏移量+长度)
抛出新的ArgumentOutOfRange(“索引”);
数组[索引]=值;
}
}
}
如果您无法复制(按照其他答案中的建议排列)并且无法更改
func
函数的签名,唯一剩下的就是尝试验证该函数没有更改数据

您可以在调用之前/之后计算某种散列,并检查它是否相同。它不能保证func没有更改基础数据(由于散列冲突),但至少可以让您知道是否发生了更改。可能对非生产代码有用


真正的解决方案是要么向不受信任的代码提供数据副本,要么传递一些不允许数据更改的包装器接口/对象(需要对
func
进行签名更改/重写)。

您是否试图确保
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!");
    }
}
不过,对于任何重要/关键的事情,我都不愿意推荐这个。你能提供更多的信息吗?也许有更好的方法来解决你的问题,并且完全避免这个问题