首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >流继承:哪些方法要覆盖?

流继承:哪些方法要覆盖?
EN

Stack Overflow用户
提问于 2020-05-07 08:54:51
回答 1查看 1K关注 0票数 1

我需要包装现有的Stream实例,并在读写时实现一些附加逻辑。

包装器也必须是Stream。它将被传递给第三方API,它需要Stream (因此,我无法提取接口并使用DispatchProxy)。

显而易见的方法是像这样从Stream继承:

代码语言:javascript
运行
复制
public sealed class WrappedStream : Stream
{
    private readonly Stream inner;

    public WrappedStream(Stream inner)
    {
        this.inner = inner;
    }

    public override bool CanRead => inner.CanRead;

    public override bool CanSeek => inner.CanSeek;

    public override bool CanWrite => inner.CanWrite;

    public override long Length => inner.Length;

    public override long Position 
    { 
        get => inner.Position;
        set => inner.Position = value; 
    }

    public override void Flush() => inner.Flush();

    public override long Seek(long offset, SeekOrigin origin) => inner.Seek(offset, origin);

    public override void SetLength(long value) => inner.SetLength(value);

    public override int Read(byte[] buffer, int offset, int count)
    {
        // TODO: implement additional logic here

        return inner.Read(buffer, offset, count);
    }

    public override void Write(byte[] buffer, int offset, int count)
    {
        // TODO: implement additional logic here

        inner.Write(buffer, offset, count);
    }
}

但是Stream中的所有抽象方法都是用于同步I/O的,我怀疑,在只实现抽象方法的情况下,基本Stream将执行异步过同步。

因为inner可以支持异步,所以我不想用异步过同步来破坏这种支持。在水龙头中有几个虚拟的APMStream方法,但是为了正确的异步I/O支持,它们中的哪一个应该被覆盖?

更新

我读了“给执行人员的说明”。如果继承类型没有实现自己的Stream方法,基本Begin...就会进行异步过同步.例如,FileStream使用自己的异步实现。因此,尽管基本实现可以工作,但从异步I/O的角度来看,它并不有效。

EN

回答 1

Stack Overflow用户

发布于 2020-05-07 09:14:18

来自文档

在实现Stream的派生类时,必须为Read(Byte[], Int32, Int32)Write(Byte[], Int32, Int32)方法提供实现。异步方法ReadAsync(Byte[], Int32, Int32)WriteAsync(Byte[], Int32, Int32)CopyToAsync(Stream)在其实现中使用同步方法Read(Byte[], Int32, Int32)Write(Byte[], Int32, Int32)。因此,Read(Byte[], Int32, Int32)Write(Byte[], Int32, Int32)的实现将正确地与异步方法一起工作。ReadByte()WriteByte(Byte)的默认实现创建一个新的单元素字节数组,然后调用Read(Byte[], Int32, Int32)Write(Byte[], Int32, Int32)的实现。当您从Stream派生时,我们建议您重写这些方法来访问您的内部缓冲区(如果您有),以获得更好的性能。您还必须提供CanReadCanSeekCanWriteFlush()LengthPositionSeek(Int64, SeekOrigin)SetLength(Int64)的实现。 不要覆盖Close()方法,而是将所有Stream清理逻辑放在Dispose(Boolean)方法中。有关更多信息,请参见实现Dispose方法。

总之,需要实现一组方法/属性:

  • Read(..)Write(..)CanWriteFlush(..)LengthPositionSeek(..)和`SetLength(.)

如果您可以提供更好的默认实现,那么所有其他虚拟方法都应该被覆盖。

因此,如果您能够实现一个真正的异步ReadAsync(..)WriteAsync(..),那么您应该这样做。FlushAsync(..)CopyToAsync(..)DisposeAsync(..)也是如此。

还请看一下源代码

代码语言:javascript
运行
复制
...

public virtual int ReadTimeout
{
    get => throw new InvalidOperationException(SR.InvalidOperation_TimeoutsNotSupported);
    set => throw new InvalidOperationException(SR.InvalidOperation_TimeoutsNotSupported);
}

public virtual int WriteTimeout
{
    get => throw new InvalidOperationException(SR.InvalidOperation_TimeoutsNotSupported);
    set => throw new InvalidOperationException(SR.InvalidOperation_TimeoutsNotSupported);
}

...

如果您想要支持ReadTimeoutWriteTimeout,您也应该重写它。

票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/61653712

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档