背景:
与this question类似,我希望将IDisposable用于除了它的设计之外的其他东西.
目标:
这个应用程序并不是非常相关,但仅仅是一个很好的例子:我有一个Windows Forms应用程序,我实现了一个Undo设计模式.通常,这是通过拦截UI元素中的“Value Changed”事件来完成的.对于DataGridView,CellEndEdit等等.但是在某些情况下,我会以编程方式更改数据,并且我希望每个撤消操作都跟踪它们,而不跟踪它们.
至今:
我有办法完成所有这些,但我在计算中管理我的“我应该撤消”逻辑:
private int _undoOverrides = 0; public bool ShouldUndo { get { return _undoOverrides < 1; } } public void DoNotUndo() { ++_undoOverrides; } public void ResumeUndo() { --_undoOverrides; }
现在,这很好用,但你必须记住在以DoNotUndo()开头的业务逻辑结束时调用ResumeUndo().我想:
Maybe I’m not too much of an idiot to screw that up,but what if I had to expose this interface in code I pass down? I would like if the compiler could take care of this for me,if possible.
想法:
我正在考虑使用一个实现IDisposable的类.这样,我的代码的用户可以使用使用块,从不担心家务杂事.这是我到目前为止:
private static int _refCount = 0; public static int ReferenceCount { get { return _refCount; } } class HallPass : IDisposable { protected bool bActive; public HallPass() { ++Program._refCount; bActive = true; Console.WriteLine("Acquired hallpass!"); } public void Dispose() { if (bActive) --Program._refCount; bActive = false; Console.WriteLine("Hallpass expired!"); } }
我包含了一个布尔值,所以我确信我不会在Dispose()上重复计算.因此,使用HallPass所需要做的就是:
using (new HallPass()) { // do things... }
问题是:
这是一个好主意吗?为什么这可能是一个坏主意?我应该知道的任何陷阱?
而且,我觉得这很愚蠢,但我很确定引用计数不适合它.它就像一个引用计数,但没有提及管理或内存来释放.编辑:可能是,现在不是.
它就像一个互斥体或一个关键部分,你试图在一段代码中做一个例外(另一个用词不当,因为我不是指你抛出的那种),但它不是那些因为它们“意味着在范围内相互排斥 – 如果您愿意,这可以通过嵌套方式完成.这就是为什么它是一个计数,而不是一个布尔值.
解决方法
下一个也是更大的问题是你并没有真正按照它应该使用的方式使用一次性模式.我个人认为,使用模式应该使用它是很重要的,特别是当你不是唯一正在处理代码的人时.
>现在您需要记住必须调用Dispose(),而不是记住调用ResumeUndo().问题是:你的团队成员是否自然会意识到他们需要在使用HallPass时调用Dispose()? (using语句很好,但不能在每个场景中使用.如果有一个HallPass的寿命超过单个方法的范围,你不能将它包装在using语句中)>虽然忘记在IDisposible上调用Dispose()是不好的,但它通常不会影响程序的正确性 – 是的,您的程序会出现性能问题,泄漏等,但从功能上来说它通常仍然是正确的.但是对于你的HallPass,如果有人忘记调用Dispose(),我想会有一个功能错误.这个bug很难追查.