C# .NET流类的设计是否糟糕?
我花了很多时间熟悉.NET流类。通常,我通过研究专业的、商业级框架的类设计学到了很多东西,但我不得不说,这里有些东西不太好闻 System.IO.Stream是表示字节序列的抽象类。它有10个抽象方法/属性:C# .NET流类的设计是否糟糕?,c#,.net,oop,stream,abstract-class,C#,.net,Oop,Stream,Abstract Class,我花了很多时间熟悉.NET流类。通常,我通过研究专业的、商业级框架的类设计学到了很多东西,但我不得不说,这里有些东西不太好闻 System.IO.Stream是表示字节序列的抽象类。它有10个抽象方法/属性:Read、Write、Flush、Length、SetLength、Seek、Position、CanRead、CanWrite、CanSeek。如此多的抽象成员使得从中派生变得很麻烦,因为您必须重写所有这些方法,即使大多数方法最终只是抛出NotImplemented 流类的用户需要调用Ca
Read、Write、Flush、Length、SetLength、Seek、Position、CanRead、CanWrite、CanSeek
。如此多的抽象成员使得从中派生变得很麻烦,因为您必须重写所有这些方法,即使大多数方法最终只是抛出NotImplemented
流类的用户需要调用CanRead
、CanWrite
或CanSeek
来了解流的功能,或者我想直接调用Read
、Write
或Seek
,看看它是否抛出未实现的。只是我,还是这个蹩脚的设计
虽然我想在流
类设计中挑很多毛病,但我想问的主要问题是:为什么他们不使用接口,比如IReadable
,IWriteable
,ISeekable
?然后,一个新的流类可以优雅地从它支持的接口派生。这不是面向对象的方式吗?还是我遗漏了什么
更新:有人指出,CanRead
等值可能在运行时发生变化,例如,如果关闭了FileStream
,则取该点。然而,我仍然不相信这是一个好的设计。从我的家乡来看,试图读取已经关闭的文件是一个错误,或者至少是一个例外情况。(因此,抛出异常是处理这种情况的自然方式。)
这是否意味着每次我要从流中读取,我都应该选中CanRead
?如果值可能在CanRead
调用和Read
调用之间的某个时间发生变化,这是否意味着我应该设置一个锁以避免竞争条件
2010年8月7日更新:这里的共识似乎是,目前的河流设计相当不错。但让我再问一次,只是为了100%确定:人们每次阅读流时都在写这样的东西
// s is a Stream
lock(s)
{
if (s.CanRead)
{
s.Read(buf, 0, buf.Length);
}
}
使用接口意味着“CanRead”的值在运行时无法更改。“FileStream”类根据文件的当前状态更改“CanRead”属性。我认为这些类设计得很好。我更愿意检查一个属性,然后尝试做一些事情,并且必须捕获一个异常。在流类型为多个“类型”的情况下,接口不足。获取可读写流的方法将返回什么类型?我同意这个设计不是一个真正的面向对象的设计,但是你真的想用那种方式来处理流吗?如果流关闭或其他更改,某些属性可能会更改,在这种情况下会发生什么
我认为这个问题带来了一个非常有趣的实验,为什么不尝试设计自己的流相关类呢。将您的重新设计发布在CodePlex或Google Code上,这将是一次很棒的学习体验,并将为其他人提供一个潜在的有用库 他们可能没有使用接口,因为当时没有扩展方法。如果希望每个流都有默认的ReadByte方法,则需要使用类
几个月前,我写了一篇关于为什么我不喜欢IO.Stream以及我认为应该做什么的文章。本质上,它归结为流不是非常类型安全的。接口可能被过度使用,这就是其中之一。我觉得现在的设计很棒。流可以在运行时更改功能这一事实意味着IReadable/IWritable/ISeekable不会消除对CanRead、CanWrite和CanSeek的需求,因此您只会增加复杂性,除了在派生类中消除少量存根方法和属性之外,没有任何实际好处
就我个人而言,我更喜欢流类更易于使用,而不是更易于编写,因为您只需编写一次并多次使用它。您可以采用(Java*)方法编写一个大部分为空的MyStream
类,该类继承了基本流
类,但提供了大多数成员方法(例如,CanSeek()
)并用合理的默认行为构建它们(例如,抛出未实现的)。然后,您真正的类只需扩展您的MyStream
类,实现您真正需要的其余两个或三个方法
当您重新使用MyStream
类时,您将节省大量对轮子的重新发明
*这在Java库中称为抽象适配器类。类流使用可选的功能模式,您可以阅读更多。我对流类的问题是长度属性-它没有指定如何实现未知、未指定或无限长的流 回答这个问题:可能吧
我非常同意@Strilanc的回答,是的,它的实现很差,但我想我还是继续发表我的想法
虽然使用可组合的接口和扩展方法(现在已经有了)来实现这些东西肯定会更干净,.NET1没有这些特性,所以我可以理解他们为什么选择这样设计
然而,现在我们有了真正有用的构造,比如泛型和扩展方法,我认为是时候重新访问许多原始类并用它们来标记它们了。当然,您首先需要一个替换API
将允许这些类在simul