【发布时间】:2009-07-31 06:04:23
【问题描述】:
.NET 中有一种相当常见的模式用于测试类的功能。这里我将使用 Stream 类作为示例,但问题适用于所有使用此模式的类。
该模式是提供一个名为 CanXXX 的布尔属性,以指示该类上的能力 XXX 可用。例如,Stream 类具有 CanRead、CanWrite 和 CanSeek 属性,以指示可以调用 Read、Write 和 Seek 方法。如果属性值为 false,则调用相应的方法将导致抛出 NotSupportedException。
来自有关流类的 MSDN 文档:
根据底层数据源或存储库,流可能仅支持其中一些功能。应用程序可以使用 CanRead、CanWrite 和 CanSeek 属性查询流的功能。
CanRead 属性的文档:
在派生类中重写时,获取一个值,指示当前流是否支持读取。
如果从 Stream 派生的类不支持读取,则调用 Read、ReadByte 和 BeginRead 方法会引发 NotSupportedException。
我看到很多代码都是这样写的:
if (stream.CanRead)
{
stream.Read(…)
}
请注意,没有同步代码可以以任何方式锁定流对象——其他线程可能正在访问它或它引用的对象。也没有捕获 NotSupportedException 的代码。
MSDN 文档没有说明属性值不能随时间改变。事实上,当流关闭时,CanSeek 属性变为 false,展示了这些属性的动态特性。因此,没有合同保证上述代码 sn-p 中对 Read() 的调用不会引发 NotSupportedException。
我预计会有很多代码存在这个潜在问题。我想知道那些发现这个问题的人是如何解决这个问题的。这里适合哪些设计模式?
我也很感谢 cmets 关于这种模式的有效性(CanXXX、XXX() 对)。对我来说,至少在 Stream 类的情况下,这代表了一个试图做太多事情的类/接口,应该分成更基本的部分。缺乏严格的记录合同使得测试变得不可能,实施变得更加困难!
【问题讨论】:
-
我相信这是对当前有效问题的出色展示。 +1
标签: .net design-patterns stream reliability