Cha*_*phs 3 c# exception-handling anti-patterns
TL; DR - 在IDisposable.Dispose中执行业务逻辑是否合适?
在我寻找答案时,我通读了一个问题:使用IDisposable和"使用"作为获取异常安全的"范围行为"的手段是否滥用?它非常接近于解决这个问题,但我想对它进行攻击.我最近遇到了一些看起来像这样的代码:
class Foo : IDisposable
{
public void Dispose()
{
ExecuteSomeBusinessBehavior();
NormalCleanup();
}
}
Run Code Online (Sandbox Code Playgroud)
并用于以下环境:
try
{
using (var myFoo = new Foo())
{
DoStuff();
foo.DoSomethingFooey();
...
DoSomethingElse();
Etc();
}
}
catch (Exception ex)
{
// Handle stuff
}
Run Code Online (Sandbox Code Playgroud)
看到这段代码后,我立即开始发痒.这是我看到这段代码时看到的内容:
首先,仅查看使用情况,当代码离开使用范围时,实际的业务逻辑(而不仅仅是清理代码)将会被执行,这一点并不明显.
其次,如果"使用"范围内的任何代码抛出异常,则Dispose方法中的业务逻辑仍将执行,并且在Try/Catch可以处理异常之前执行此操作.
我对StackOverflow社区的问题是:将业务逻辑放在IDisposable.Dispose方法中是否有意义?是否有一种模式可以实现类似的结果而不会让我发痒?
(对不起,这更像是评论,但超出了评论长度限制.)
实际上,在.NET框架中有一个示例,其中IDisposable用于创建范围并在处置时执行有用的工作:TransactionScope.
调用此方法标记事务范围的结束.如果TransactionScope对象创建了事务并且在作用域上调用了Complete,则在调用此方法时,TransactionScope对象将尝试提交事务.
如果您决定采取这种方式,我会建议
你明确表示你的对象创建了一个范围,例如,通过调用它FooScope来代替Foo和
你会非常认真地思考当异常导致代码离开你的范围时会发生什么.在TransactionScope,Complete块的末尾调用模式确保Dispose可以区分这两种情况.