虽然我一直觉得王垠这个人混身槽点(我看这文的第一反应是吐槽他竟然不知道.Net Reference Source),但是这篇文章的观点是要支持的(想看干货不想听吐槽的可以直接跳到正文)。王垠
IDisposable本来就一个很容易误用,然后误用了之后又很容易扩散开来的一个pattern。现在.Net类库里IDisposable的滥用愈演愈烈,我觉得有原因有几个
有些非常基本的类,当初设计的时候有一些妥协和Trade Off,有不完美的地方,但很不明白设计背后的Trade Off,把那个当成最佳实践来盲从,比如Stream上的Dispose方法,比如说Using语句。我们后面细说。
大公司的官僚文化。王垠大家常常拿稳定性扩展性说事儿,导致有一种“不管有没有用,反正我现在先加了就不会被说了”的甩锅心理(某答主很诚实地说出了这种的想法大家可以去看看)。于是在一些不需要用IDisposable的地方用上了IDisposable,产生了一些错误实践。
微软对Compiler Warning的变态执着(产品编译全部使用Warning as Error,并且大部分Warning不允许直接Suppress,定期会看Suppress的数量有没有增加)导致大家为了消除那个Disposable的warning,到处乱加代码。
上面说的错误实践,因为重复得太多次,反而被当成了正确实践,最终导致这个问题不可收拾。Ivony的回答,基本上总结了大部分人对IDisposable的看法,可惜的是,绝大部分其实根本是错误实践,正文里有具体的分析。
这个问题严重到出现了虽然Task实现了Dispose,但你不应该去调用,这种诡异的情况:
Do I need to dispose of Tasks?
<><><><><><>以下是正文<><><><><><>
要讨论IDisposable在.Net有没有被滥用,首先我们要知道它是干嘛用的,虽然大家看似都知道,但常常用起来就忘记了,然后导致很多错误实践,所以我们来一起回顾一下:
IDisposable Intece (System)
Provides a mechanism for releasing unmanaged resources.
重点显然有两个,一个是释放资源,另一个是非托管。
明白这个,首先就可以知道,在HashAlgorithm上面, @Belleve 的反对没有道理,确实需要把数组清零,但这个功能不应该实现成Dispose方法。这个错误其实是一个常见的滥用,常常会有这样的思路:”这个最终的Cleanup是一定要做的,所以我应该放在Dispose里,这样如果你不调用就会有warning了。“这样想的人,显然已经忘记Dispose设计出来只想处理非托管资源这件事了。会犯这种错误的人常常是从C++转过来的,把Dispose和析构的定位混淆了。C++的析构是这样的:
Destructor (computer programming)
a destructor (dtor) is a method which is automatically invoked when the object is destroyed
它并不管你想在析构函数里做法。那么为什么C#的Dispose要定义得这么精确,而C++的析构却很宽泛呢?这是因为C++的析构没有传播性可以使用得更宽泛些,而C#的Dispose有极强的负面作用要限制它的使用场景。所以说语言和语言虽然很多概念相似,但常常差之毫厘失之千里。
本文来自电脑杂谈,转载请注明本文网址:
https://www.pc-fly.com/a/ruanjian/article-46198-1.html
这也是后来的战列舰大战通常采取的战法
0