我们有构造函数,我们可以将它们视为对象实例化所遵循的契约。
没有为构造函数提供精确的参数集,没有其他方法可以创建实例。
但我们怎么能(而且我们应该打扰)强制执行一些验尸活动?
我们已经有了终结器,但不建议将它们用于通用定型。
我们还有IDisposable
来实施。但是如果我们使用没有using
的一次性对象,我们无法保证会调用Dispose。
为什么现在有办法强制对象的某些状态才会被释放?
终结终结器是不可能的,因为不能保证对象图是完整的,并且GC的引用对象没有被清空。
当然,不是通过客户端代码调用实例对象的SaveState()
会给它带来一些麻烦,而不是我的对象。
尽管如此,要求在构造函数中注入所有必需的依赖项(如果没有可用的默认值)是一种很好的做法。没有人容易说:“如果对象处于无效状态,请保留默认构造函数,创建属性并抛出异常。”
更新
由于有很多投票要结束这个问题,我会说一些设计模式也可以作为答案。
无论您是否使用DI,您都可以计算请求/创建对象的次数。但是如果没有明确的释放电话,你就不知道你何时应该召集处理。
我根本不明白如何在适当的时候实施处置。
答案 0 :(得分:12)
为什么在它被释放之前没有办法强制执行对象的某些状态?
因为垃圾收集器的重点是 simulate a machine that has an infinite amount of memory 。如果记忆是无限的,那么你永远不需要清理它。
您正在混淆程序的语义要求 - 在特定时间发生特定的副作用 - 使用模拟无限存储的机制。在一个理想的世界里,这两件事不应该彼此有任何关系。不幸的是,我们不是生活在理想的世界里;终结者的存在就是证据。
如果您想要在特定时间实现效果,那么这些效果是您的程序的一部分,您应该编写实现它们的代码。如果它们很重要,那么它们应该在代码中可见,以便阅读代码的人可以看到并理解它们。
答案 1 :(得分:2)
不幸的是,在Java的设计过程中,预计垃圾收集器应该能够满足所有清理要求。这似乎也是.NET早期设计阶段的一个信念。
因此,没有区别:
object reference
,它封装了目标的独占所有权;
不封装所有权的reference to an object
(其目标由其他人拥有);
reference whose owner
知道它将封装独占所有权或封装无,并知道哪种情况适用于手边的实例; < / p>
或封装共享所有权的object reference
。
如果围绕这些区别正确地设计了一种语言和框架,那么很少有必要编写代码,以便无法对静态验证进行适当的清理(前两种情况,可能适用于90%以上的情况,可能很容易即使使用.NET框架也可以进行静态验证。
不幸的是,因为在using
语句的非常有限的上下文之外不存在这样的区别,所以当一段代码放弃引用时,编译器或验证器无法知道是否还有其他东西需要清理提到由此提到的对象。
因此,一般无法知道对象应该是否应该被处置,并且没有通常有意义的方式来发出声音,如果它应该但不是。