阅读答案后在这里 ,我决定以纪念我的课,如为了简化密封的IDisposable实现。 为什么密封影响IDisposable的实施(如GC.SuppressFinalize(this);
并不需要被调用)? 请解释发生了什么。 我需要能够为什么我做密封类来解释研究员开发商。
Answer 1:
如果它实现了类IDisposable
是不密封的,很可能是一个派生类将需要做一些应对Dispose
,但对于基础类的行动Dispose
应进行为好。 如果该类公开了一个公共Dispose
成员将永远伴随着代名词IDisposable.Dispose
,必要的语义可以在C#中通过简单地使用隐式接口实现与公共虚拟实现Dispose
方法。
有两个问题与方法:
- 它需要派生类使用在父暴露了公共`Dispose`方法,比在它没有案件的情况不同的方法; 如果不公开公共`Dispose`方法的类由未密封类继承做事情会变得非常泥泞。
- 一些基处置代码衍生类处置代码(例如,其抑制重复`Dispose`尝试的代码)之前应该运行,以及一些应后(例如`GC.SuppressFinalize()`)上运行。 实现这一点的唯一方法是有一个非虚拟包装调用一个受保护的虚拟功能。 请注意,顺便说一句,微软的包装不恰当地抑制重复-`Dispose`,但包装是这种抑制代码唯一不好的地方。
请注意,微软似乎已经预期其Dispose
方式在一个基类没有覆盖的情况下被使用Finalize
,但派生类使用Finalize
了清理。 虽然这可能是意图,它不是用于这一目的的良好格局。 除了极少数例外,它应该只覆盖只有类Finalize
为清理是那些从琐碎的类,如派生Object
。 如果一个类实现IDisposable
,但不覆盖Finalize
,为此,派生类应重写的唯一目的Finalize
是敲响警钟,如果Finalize
曾经被调用,而即使是使用是值得商榷的(一个更好的模式是:
class whatever:IDisposable { IDisposable DisposedStatusObject; // Generate a static dummy object instance we can use as a sentinel value // It needs to be `IDisposable`, but shouldn't actually hold any resources. static IDisposable DisposedStatusDisposed = new List<int>().GetEnumerator(); public bool Disposed {get {return (DisposedStatusObject == DisposedStatusDisposed);} } whatever() { DisposedStatusObject = new DisposalAlarm(); // First thing in constructor } void Dispose() { IDisposable prevStatus; prevStatus = Interlocked.Exchange(DisposedStatus, DisposedStatusDisposed); if (prevStatus != DisposedStatusDisposed) { Dispose(true); prevStatus.Dispose(); } } }
所述DisposalAlarm()
类被假定为与一个重写的一个类Finalize()
如果其发出警报的方法Finalize()
方法被调用没有其Dispose()
方法被首先被调用。 该Dispose
方法, whatever
将确保,如果派生类的方法返回正确,报警器将被取消。 需要注意的是,如果一个实例whatever
有非抑制终结,一切都到whatever
拥有直接或间接引用将不得不围绕保持,直到终结已经运行或被抑制。 相比之下,另外一个的DisposalAlarm
对象不延长在任何寿命whatever
。
Answer 2:
制备类sealed
意味着不可能有从它派生的类。 这意味着,实施IDisposable
并不需要考虑行为(或行为不当)派生类的。
Answer 3:
密封类并不旨在被用作基类,而未密封的类是。 因此,位于区别:未密封类需要为它的派生类提供一种方法来实现Dispose()
自己的,而一个密封类是免费的这个责任,因为它不能扩展。