重构:使用没有作用域的using语句,隐式的Dispose调用何时发生?

9

前几天我在重构代码时,遇到了这样的情况:

public async Task<Result> Handle(CancelInitiatedCashoutCommand command, CancellationToken cancellationToken)
{
    using (_logger.BeginScope("{@CancelCashoutCommand}", command))
    {
        return await GetCashoutAsync(command.CashoutId)
            .Bind(IsStatePending)
            .Tap(SetCancelledStateAsync)
            .Tap(_ => _logger.LogInformation("Cashout cancellation succeeded."));
    }
}

Resharper建议将其重构为:

public async Task<Result> Handle(CancelInitiatedCashoutCommand command, CancellationToken cancellationToken)
{
    using var scope = _logger.BeginScope("{@CancelCashoutCommand}", command);
    return await GetCashoutAsync(command.CashoutId)
        .Bind(IsStatePending)
        .Tap(SetCancelledStateAsync)
        .Tap(_ => _logger.LogInformation("Cashout cancellation succeeded."));
}

我有点怀疑,实际上我不确定第二个版本中隐式Dispose调用会在什么时候发生。

我该如何知道呢?


using var scope = ...; 的意思是在离开 Handle 作用域时,scope 将被 Disposed - Dmitry Bychenko
所以基本上包含该语句的方法。 - Natalie Perret
你看过文档了吗?如果有的话,有什么不清楚的地方吗?顺便说一下,你可以通过实现自己的测试类 public class TestDispose : IDisposable { public void Dispose(){ Console.WriteLine("disposing"); }} 来测试它何时被调用。 - germi
1
对于像日志范围和事务之类的东西,如果使用块显式指示范围,则代码可能仍然更清晰,尤其是因为日志范围通常没有命名。如果在功能上您并不真正关心资源何时被处理(例如SqlConnection),则“using var”非常有用。在所有情况下,“Dispose”时刻都是确定的,但是当不是特别重要时,可以省略“using var”的范围。当然,这是主观的,这就是为什么Resharper坚持建议的原因。 - Jeroen Mostert
我确实查阅了文档,但它看起来非常奇怪,感觉不对。我也进行了自己的检查,确实在之后调用了dispose,但我不确定编译器是否可以在其他情况下更改重写(和隐式dispose调用)。 - Natalie Perret
3个回答

6

Resharper建议使用C# 8.0的using声明特性:using declarations

 public async Task<Result> Handle(CancelInitiatedCashoutCommand command, 
                                  CancellationToken cancellationToken)
 {  
    using var scope = ...;
    ...
 } // <- scope will be Disposed on leaving its scope (here on Handle method's scope)

4
我也在想同样的事情。using声明在方法结束时移出作用域,然后被处理掉。Microsoft文档表示:
“当方法的右括号到达时,文件将被释放。那是file声明的作用域的结尾。”
似乎如果您有一个using语句,它会在using括号的结尾处处理变量,而不是仅在方法结束时处理using声明的变量。如果您在watch或locals窗口中查看此内容,则会立即看到其移出作用域。https://dirkstrauss.com/c-sharp-8-0-using-declarations/

4
那是一个C#8 using语句,当变量本身超出作用域时,被scope引用的对象将被销毁。
在这种情况下,即在您的Task完成后。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接