考虑到IDisposable的语义,除了清理资源之外,Dispose应该做什么呢?
我看到许多类使用Dispose方法来启动关闭进程和其他一些东西,而不只是执行“资源清理”工作。例如,如果你的类中有一个线程需要关闭,那么你会期望调用Dispose正常关闭这个线程吗?
恕我直言,我会在这个对象上实现一个停止/关闭方法,然后优雅地关闭那里的线程,而在Dispose中我会检查线程何时还活着,只需在它上面调用Abort(暗杀样式:))。
同样的例子可以是定时器,以及所有其他资源,在完成你使用该对象之前可以有某种终止过程。
.NET中两个冲突设计的例子:
答案 0 :(得分:2)
很难,我使用dispose 只做做业务逻辑。例如:
public class UsingBase : IDisposable
{
protected Action end;
public UsingBase(Action start, Action end) { this.end = end; if (start != null) start(); }
public void Dispose() { if (end != null) end(); }
public void Cancel() { end = null; }
}
class HideCursor : UsingBase { public HideCursor() : base(() => Console.CursorVisible = false, () => Console.CursorVisible = true) { } }
public static void DisplayTitle(...)
{
...
using (new HideCursor())
{
//Display the title
}
...
}
虽然有些人可能认为这是滥用语言,但我从ASP.net API中得到了这个想法。
@using (Html.BeginForm())
{
...
}
回到你的问题
例如,如果您在类中有一个线程,则需要 关闭,你会期望调用Dispose正常关闭 这个帖子?
我喜欢它,当它有意义时 - 因为我经常使用对象使用它,让它自己处理它。当然,如果您清楚地记录了您的逻辑,并且有明确的理由将“优雅停止”与“处置”区分开来,那么这可能有用。
或换句话说 - 我不想无缘无故地这样做:
using (var blah = new Blah())
{
...
...
...
Blah.SpecialDispose();
}//Blah.Dispose();
因为它会导致使用试图停止的确切问题 - 人们忘记编写正确的包装代码(例如,最后尝试)。
编辑:
总结。是的,业务逻辑可以完成Dispose。是的,Dispose可以很好地处理事情。这些是你提出的主要问题。但是,这并不一定否定可能的用例,其中Dispose被用作“最后手段”并且在其行为中更加突然。听起来你对自己的用例充满信心,在这种情况下继续。如果您仍想要反馈,我建议发布一个与您的实际用例相关的更具体的问题。
答案 1 :(得分:1)
不要考虑IDisposable
合同,而是将IDisposable
视为一般Object
合同的一部分更有帮助,该合同规定对象不应要求任何形式的在放弃之前注意除 IDisposable.Dispose
之外的其他文件(未实现IDisposable
的对象根本不需要任何通知)。 <{1}}方法应该做任何事情,并且在安全放弃对象之前需要完成所有事情。
这个问题的唯一方面是执行清理时可能会出现异常,Dispose
无法知道在这种情况下它应该做什么。如果在正常(非异常)程序执行期间调用Dispose
,则在清理失败时应抛出异常。但是,如果在从异常中展开堆栈时调用它,则它可能抛出的任何异常通常都会破坏先前异常的所有证据(因此通常会更好地使它无声地失败而不是抛出异常)。不幸的是,Dispose
无法确定哪种情况适用,因此无法在清理失败的情况下始终如一地做正确的事情。