王垠_王垠清华梦的粉碎_王垠现状(3)

电脑杂谈  发布时间:2017-05-09 23:12:04  来源:网络整理

this.stream = CreateMemoryStream();

this.disposableObject = null;

另一边在Cleanup里

if (this.disposableObject != null) { this.disposableObject.Dispose(); }

显然这样写起来比较麻烦。写程序是一个工程性的事情,常常为了现实而在设计上有所妥协,就像的范式,虽然模式上当然符合范式最正确,但常常在实际上会选择有意识地违犯范式。如果考虑到事实上只有MemoryStream这一个不需要释放资源的特例,而几乎所有的其它Stream都有释放非托管资源的需求,于是为了方便,所以在Stream的设计上做了一个妥协,没有用最正确的法法,而是选了一个相对比较方便的做法。把这种有意识的trade off,当成是一个设计上的最佳实践,就变成搞笑的事情了。所以基于OO的设计原则,结论是这样的:

应该避免在基类和接口上实现IDisposable。基类也好接口也好应该优先保证自己职责的纯洁性。

如果确定所有的子类都会需要实现IDisposable,可以选择实现IDisposable,但更好的做法是实现intece IFoo, 以及intece IDisposableFoo : IFoo, IDisposable。从而保证decoupling.

如果你觉得子类可能实现也可能不实现,那就把选择权留给子类,而不是在基类强制决定。这种虚假的可扩展性,常常是代码变得完蛋的开始。

接下来说一下,Ivony的回答里的第三个场景。看到有人拿StreamWriter来当好的设计的例子,这还真有点搞笑,要知道StreamWriter/Reader简直是一个OO设计失败案例的集大成之作。StreamWriter的设计意图是好的,它是这么一个东西:一个可以向任何Stream里写入数据的工具类。本质上和上面那个例子里的ProcessStream函数是一个东西。我们都知道应该由一个stream的owner来调用Dispose,那么StreamWriter完全应该不需要去调用Dispose才对呀,代码怎么也应该长成下面这个样子:

using(stream s = CreateFileStream(...))

{

StreamWriter sw = new StreamWriter(s, ..);

sw.Write(...);

}

怎么StreamWriter就突然需要去Dispose了呢,或者换个问法,怎么StreamWriter突然变成Stream的Owner了呢?仔细研究一下就会发现,这是因为StreamWriter支持你直接输入一个文件名,然后它会创建一个FileStream,这才是问题的根源。有基础OO设计常识的人都知道这是一个特别错误的设计,把一个提供通用功能的类,和一个具体的场景给耦合起来了。正确的做法应该是引入一个FileWriter来负责创建FileStream,并调用StreamWriter来实现写入的功能。StreamWriter就不再需要实现IDisposable,而FileWriter是它创建的FileStream的owner,而FileStream本身是disposable,所以FileWrtier需要实现IDisposable。同样的这种设计并不需要Stream基类提供Dispose方法。(题外话:每个学C#的新手,都应该吐槽过为什么StreamWriter不叫FileWriter,导致初学的人根本找不到哪个类是实现这个功能的)

最后总结一下,其实就是两点:

有非托管资源的时候要实现IDisposable。

是一个disposable对象的owner的时候要实现IDisposable。

非要再加一条的话,就是不确定的时候,就不要实现IDisposable。毕竟IDisposable的负面作用太大。

而这两条原则和王垠推荐的那文里完全一样。所以王垠对这个问题的看法显然是正确的。


本文来自电脑杂谈,转载请注明本文网址:
https://www.pc-fly.com/a/ruanjian/article-46198-3.html

相关阅读
    发表评论  请自觉遵守互联网相关的政策法规,严禁发布、暴力、反动的言论

    热点图片
    拼命载入中...