Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/321.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 让溪流流过的最好方法是什么_C#_Stream_Arguments - Fatal编程技术网

C# 让溪流流过的最好方法是什么

C# 让溪流流过的最好方法是什么,c#,stream,arguments,C#,Stream,Arguments,我曾尝试将stream作为一个参数传递,但我不确定哪种方式是“最好的”,因此希望听到您对我的代码示例的意见/建议 我个人更喜欢选项3,但在其他地方我从未见过这样做 选项1适用于小型流(以及已知大小的流) 选项2_1和选项2_2总是让“交易人”怀疑谁有责任处置/交割 public interface ISomeStreamHandler { // Option 1 void HandleStream(byte[] streamBytes); // Option 2

我曾尝试将stream作为一个参数传递,但我不确定哪种方式是“最好的”,因此希望听到您对我的代码示例的意见/建议

我个人更喜欢选项3,但在其他地方我从未见过这样做

选项1适用于小型流(以及已知大小的流)

选项2_1选项2_2总是让“交易人”怀疑谁有责任处置/交割

public interface ISomeStreamHandler
{
    // Option 1
    void HandleStream(byte[] streamBytes);

    // Option 2
    void HandleStream(Stream stream);

    // Option 3
    void HandleStream(Func<Stream> openStream);
}

public interface IStreamProducer
{
    Stream GetStream();
}

public class SomeTestClass
{
    private readonly ISomeStreamHandler _streamHandler;
    private readonly IStreamProducer _streamProducer;

    public SomeTestClass(ISomeStreamHandler streamHandler, IStreamProducer streamProducer)
    {
        _streamHandler = streamHandler;
        _streamProducer = streamProducer;
    }

    public void DoOption1()
    {
        var buffer = new byte[16 * 1024];
        using (var input = _streamProducer.GetStream())
        {
            using (var ms = new MemoryStream())
            {
                int read;
                while ((read = input.Read(buffer, 0, buffer.Length)) > 0) 
                {
                    ms.Write(buffer, 0, read);
                }
                _streamHandler.HandleStream(ms.ToArray());
            }
        }
    }

    public void DoOption2_1()
    {
        _streamHandler.HandleStream(_streamProducer.GetStream());
    }

    public void DoOption2_2()
    {
        using (var stream = _streamProducer.GetStream())
        {
            _streamHandler.HandleStream(stream);    
        }
    }

    public void DoOption3()
    {
        _streamHandler.HandleStream(_streamProducer.GetStream);
    }
}
公共接口处理程序
{
//选择1
void HandleStream(字节[]流字节);
//选择2
无效手流(溪流);
//选择3
无效手流(Func openStream);
}
公共接口IStreamProducer
{
Stream GetStream();
}
公共类SomeTestClass
{
私有只读流处理器_streamHandler;
私有只读IStreamProducer\u streamProducer;
公共SomeTestClass(ISomeStreamHandler streamHandler、IsStreamProducer streamProducer)
{
_streamHandler=streamHandler;
_streamProducer=streamProducer;
}
公共无效选项1()
{
var buffer=新字节[16*1024];
使用(var输入=_streamProducer.GetStream())
{
使用(var ms=new MemoryStream())
{
int-read;
而((read=input.read(buffer,0,buffer.Length))>0)
{
ms.Write(缓冲区,0,读取);
}
_streamHandler.HandleStream(ToArray女士());
}
}
}
公共无效选项2_1()
{
_streamHandler.HandleStream(_streamProducer.GetStream());
}
公共无效选项2_2()
{
使用(var stream=\u streamProducer.GetStream())
{
_streamHandler.手流(流);
}
}
公共无效选项3()
{
_streamHandler.HandleStream(_streamProducer.GetStream);
}
}

传递一个
IStream
,并在流的起始位置执行
IDisposable

处理流的责任在于创建它的对象。

选项2\u 2是处理可处置资源的标准方法

您的
SomeTestClass
实例向生产者请求一个流,然后
SomeTestClass
拥有一个流并负责清理

选项3和21依赖不同的对象来清理
SomeTestClass
所拥有的资源-可能无法满足此期望


选项1只是将一个流的内容复制到另一个流——我看不出这样做有什么好处。

您可能没有意识到这一点,但您正在尝试实现管道设计模式。作为一个出发点,考虑一下:

  • (其他良好的参考资料??)
关于您的实施,我建议您选择选项2:

关于对象寿命,我相信:

  • 实现在处理调用
    Dispose
  • 如果
    IStreamHandler
    没有调用
    Dispose
    ,您的解决方案将更加灵活(现在您可以像在Unix管道中一样将处理程序链接在一起)
第三方解决方案

构建管道解决方案可能很有趣,但也值得注意的是,市场上有一些现有产品:

附加注释

有一个设计问题与您提出的方案2有关:


在中,您可以通过将一个程序的输出作为另一个程序的输入,将多个应用程序链接在一起。如果您要使用选项2构建类似的解决方案,那么如果您使用多个处理程序,并且您的数据
Stream
仅为正向(即
Stream.CanSeek=False
),您将遇到问题。

选项3仅使用“MemoryStream”作为将流转换为字节数组的手段。-因此,这不是将流内容解析到另一个流的问题;如果您被要求在何处执行“void HandleStream(Stream);”您将假定您的实现没有责任关闭/处理流?@JakobDyrby-仍然,选项3是从
流读取、写入
内存流,并转换为
字节[]
。为什么不直接从
流中读取
,然后使用缓冲区呢?@JakobDyrby:是的。如果一次性资源(不仅仅是流)作为参数传递给我的方法,我不会假设我应该关闭它。事实上,我会说我有责任不关闭它。我不知道是谁在呼叫我,我不知道呼叫我的人是否需要进一步访问该流-因此我有义务让它保持打开状态。@JakobDyrby根据经验,关键字是所有权。无论谁拥有
IDisposable
实例,都有责任关闭它。谢谢!我将阅读该设计模式。但是现在;请你详细说明你认为谁有责任关闭这家公司。我应该使用选项2_1或选项2_2中所示的界面吗?我会选择:DoOption2_2。更重要的是:(1)与您的实现保持一致,(2)确保在意外引发异常时释放所有资源。因此,FileInfo对象有责任关闭“fi.OpenRead()”之后的流,但事实并非如此。请参阅@dcastro的评论,“根据经验,关键词是所有权。无论谁拥有IDisposable实例,都有责任关闭它。”
public interface IStreamHandler
{
    void Process(Stream stream);
}
void Process(Stream stream);