我有类MemoryStream2,它继承自MemoryStream,唯一的区别是它引入了一个新变量——引用id。现在我遇到一种情况,某个函数返回 MemoryStream,我需要将其转换/分配给 MemoryStream2。
public class MemoryStream2 : System.IO.MemoryStream
{
public string ReferenceId = "";
public MemoryStream2() : base() { }
public MemoryStream2(byte[] buffer) : base(buffer) { }
public MemoryStream2(System.IO.MemoryStream ms)
{
this.ReferenceId = DateTime.Now.ToString();
this = ms;
}
}
但是,
(System.IO.MemoryStream)this = ms;
是一个错误:
无法分配给“this”,因为它是只读的
(System.IO.MemoryStream)this = ms;
也不正确:
赋值的左侧必须是变量
那么我该怎么做呢?如何将标准 MemoryStream 分配给自定义 MemoryStream,最好不要将数据从一个流重新加载/复制到另一个流?
谢谢你
组合几乎肯定是比继承更好的选择。即
public class MemoryStream2(MemoryStream Stream, string ReferenceId)
{
public MemoryStream2(MemoryStream stream) : this(stream, DateTime.Now.ToString()){}
}
您还可以使用值元组来创建数据对,而无需创建新的显式类型,即
(MemoryStream Stream, string ReferenceId)
。继承有几个缺点,包括与基类的强耦合,因此在大多数情况下组合是首选。
您可以使用委托模式。这可能是一种有用的模式,但最适合相当小的接口。它并不真正适合
MemoryStream
,因为它并不是真正设计用于继承的。它可以与 Stream
一起使用,但由于方法数量众多,这也不理想:
public class MemoryStream2(MemoryStream Stream, string ReferenceId) : Stream
{
public MemoryStream2(MemoryStream stream) : this(stream, DateTime.Now.ToString()){}
public override void Flush() => Stream.Flush();
public override long Seek(long offset, SeekOrigin origin) => Stream.Seek(offset, origin);
public override void SetLength(long value) => Stream.SetLength(value);
public override int Read(byte[] buffer, int offset, int count) => Stream.Read(buffer, offset, count);
public override void Write(byte[] buffer, int offset, int count) => Stream.Write(buffer, offset, count);
public override bool CanRead => Stream.CanRead;
public override bool CanSeek => Stream.CanSeek;
public override bool CanWrite => Stream.CanWrite;
public override long Length => Stream.Length;
public override long Position
{
get => Stream.Position;
set => Stream.Position = value;
}
}
如果绝对必要,您可以提取后备缓冲区并将其用作新流的缓冲区,但这不是我建议的做法,因为
GetBuffer
可能会失败:
public class MemoryStream2 : MemoryStream
{
public string ReferenceId = "";
public MemoryStream2(MemoryStream stream) : base(stream.GetBuffer())
{
this.SetLength(stream.Length);
this.Position = stream.Position;
this.ReferenceId = DateTime.Now.ToString();
}
}
您还可以从现有流中复制数据,但似乎没有必要创建所有数据的完整副本,只是为了将其与引用 ID 相关联。