如果您正在设计 API,甚至在您自己的代码中,并且您的方法接受 a Stream
,那么您的方法是否有责任检查位置并将其重置为在使用它之前提供的CanSeek
开头true
?
如果是这样,为什么没有一种方法可以在Stream
类本身上完成所有这些工作?
Stream
多年来,通过假设在位置 0 进入我的方法,我已经被抓住了几次。
使用后尽可能重置是否正确Stream
?
或者,是否应该Stream
始终复制 s 而不是直接传递?对我来说似乎有点过分。
如果您正在设计 API,甚至在您自己的代码中,并且您的方法接受 a Stream
,那么您的方法是否有责任检查位置并将其重置为在使用它之前提供的CanSeek
开头true
?
如果是这样,为什么没有一种方法可以在Stream
类本身上完成所有这些工作?
Stream
多年来,通过假设在位置 0 进入我的方法,我已经被抓住了几次。
使用后尽可能重置是否正确Stream
?
或者,是否应该Stream
始终复制 s 而不是直接传递?对我来说似乎有点过分。
如果 CanSeek 在使用之前为真,您的方法是否有责任检查位置并将其重置为开头?
不,在这种情况下,我希望调用代码能够正确准备流。
在方法上共享流的最常见模式要求指针在最后一次读/写之后完全离开,所以这不会出现太多。
但是使用它后最好的事情是:什么都不做。
如果 CanSeek 在使用之前为真,您的方法是否有责任检查位置并将其重置为开头?
不,有两个原因:
CanSeek
是假的),所以如果你为某些流而不是为其他流这样做会很奇怪StreamReader
在处理底层流时关闭它,它不会将其恢复到之前的状态。我不想更新问题,因为人们已经投票但可能不喜欢这部分:)
这非常有趣(感谢),并且清楚地显示了设计可重用库样式代码与应用程序代码时的思维差异。
因此,如果它是应用程序为 API 准备的责任Stream
(而且似乎我们都同意),那么我们可以将有用的逻辑“提升”到应用程序内的扩展方法中。
/// <summary>
/// Tries to set the stream to position 0 if required.
/// </summary>
/// <returns>
/// False if the stream is not at position 0 and does not support seek operations.
/// </returns>
public static bool TrySetPositionZero(this Stream stream)
{
if (stream.Position > 0)
{
if (stream.CanSeek)
{
stream.Position = 0;
return true;
}
else
{
return false;
}
}
else
{
return true;
}
}
这和简单的区别在于stream.Position = 0
它有更多的成功机会,因为当它已经在位置 0 时,它会在仅转发流上成功。