You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何将标准MemoryStream赋值给继承自它的自定义类MemoryStream2

如何将标准MemoryStream赋值给继承自它的自定义类MemoryStream2

嘿,我来帮你捋清楚这个问题!首先得明确:你碰到的Cannot assign to 'this' because it is read-only错误是必然的——在C#里this是个只读引用,你没法直接把另一个实例赋值给它,就算强制类型转换也没用,毕竟赋值语句的左边必须是可修改的变量才行。

那回到你的核心需求:把普通的MemoryStream转成自定义的MemoryStream2,还不想复制流里的数据,该怎么实现?

为什么继承这条路走不通(不复制数据的前提下)

MemoryStream的内部缓冲区是私有成员,它也没提供公开方法让你直接替换或复用这个缓冲区。所以如果你的MemoryStream2是继承自MemoryStream,那你只能创建全新的MemoryStream2实例,把原流的数据复制进去,没法直接复用原流的内存。

如果能接受复制数据,那可以这么修改构造函数:

public MemoryStream2(System.IO.MemoryStream ms) : base(ms.ToArray())
{
    this.ReferenceId = DateTime.Now.ToString();
    // 要是需要保留原流的读取位置,别忘了同步Position
    this.Position = ms.Position;
}

但这显然不符合你“不复制数据”的要求,所以得换个思路。

最佳方案:用组合代替继承

既然继承没法直接复用原流,那我们换个思路——让MemoryStream2包装一个MemoryStream实例,而不是继承它。具体来说,让MemoryStream2实现Stream抽象类,内部持有一个MemoryStream对象,把所有流操作都委托给这个内部对象,同时加上你自己的ReferenceId属性。

这种方式的好处是:可以直接把原有的MemoryStream传入,完全复用它的缓冲区,不用复制任何数据。代码示例如下:

public class MemoryStream2 : System.IO.Stream
{
    private readonly System.IO.MemoryStream _innerStream;
    public string ReferenceId { get; set; } = "";

    // 无参构造:自己创建内部流
    public MemoryStream2()
    {
        _innerStream = new System.IO.MemoryStream();
        ReferenceId = DateTime.Now.ToString();
    }

    // 用字节数组构造
    public MemoryStream2(byte[] buffer)
    {
        _innerStream = new System.IO.MemoryStream(buffer);
        ReferenceId = DateTime.Now.ToString();
    }

    // 用现有MemoryStream构造——重点在这!直接复用原流
    public MemoryStream2(System.IO.MemoryStream ms)
    {
        _innerStream = ms;
        ReferenceId = DateTime.Now.ToString();
    }

    // 重写Stream的所有抽象/虚成员,委托给_innerStream
    public override bool CanRead => _innerStream.CanRead;
    public override bool CanSeek => _innerStream.CanSeek;
    public override bool CanWrite => _innerStream.CanWrite;
    public override long Length => _innerStream.Length;
    public override long Position
    {
        get => _innerStream.Position;
        set => _innerStream.Position = value;
    }

    public override void Flush() => _innerStream.Flush();
    public override int Read(byte[] buffer, int offset, int count) => _innerStream.Read(buffer, offset, count);
    public override long Seek(long offset, System.IO.SeekOrigin origin) => _innerStream.Seek(offset, origin);
    public override void SetLength(long value) => _innerStream.SetLength(value);
    public override void Write(byte[] buffer, int offset, int count) => _innerStream.Write(buffer, offset, count);
}

这样你就可以直接把返回的MemoryStream传入MemoryStream2的构造函数,完美复用原流的数据,还能带上你的ReferenceId。

虽然这种方式需要你写一堆委托代码,但这是实现你需求的最优解——正如你自己编辑里提到的,组合确实是目前最好的方案,稍微做点代码重构就能解决问题啦。

备注:内容来源于stack exchange,提问作者George

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.04.15 09:14:29