【问题标题】:Resharper suggesting to convert Using statements to single "await Using"?Resharper 建议将 Using 语句转换为单个“等待使用”?
【发布时间】:2019-11-20 20:46:49
【问题描述】:

Resharper 建议将带有 await 关键字的 using 语句改进为单行 await using 语句。例如,以下代码 sn -p :

    private async Task<string> ReadResponseAsync(HttpContext context)
    {
        var originalBody = context.Response.Body;

        try
        {
            using (var responseStream = new MemoryStream())
            {
                context.Response.Body = responseStream;
                await _next(context).ConfigureAwait(false);

                var response = context.Response;
                response.Body.Seek(0, SeekOrigin.Begin);

                using (var responseReader = new StreamReader(response.Body))
                { 
                    var responseContent = await responseReader
                    .ReadToEndAsync()
                    .ConfigureAwait(false);

                    response.Body.Seek(0, SeekOrigin.Begin);

                    await responseStream.CopyToAsync(originalBody)
                    .ConfigureAwait(false);
                    return responseContent;
                }
            }
        }
        finally
        {
            context.Response.Body = originalBody;
        }
    }

在应用连续的 Resharper 建议后,代码变为以下:

    private async Task<string> ReadResponseAsync(HttpContext context)
    {

        var originalBody = context.Response.Body;

        try
        {
            await using var responseStream = new MemoryStream();
            context.Response.Body = responseStream;
            await _next(context).ConfigureAwait(false);

            var response = context.Response;
            response.Body.Seek(0, SeekOrigin.Begin);

            using var responseReader = new StreamReader(response.Body);
            var responseContent = await responseReader
                .ReadToEndAsync()
                .ConfigureAwait(false);

            response.Body.Seek(0, SeekOrigin.Begin);

            await responseStream.CopyToAsync(originalBody)
                .ConfigureAwait(false);
            return responseContent;
        }
        finally
        {
            context.Response.Body = originalBody;
        }
    }

这两个代码 sn-ps 相似吗?这里实际上正在改进什么?对于 using 语句,我不理解 C# 的这一特性。

【问题讨论】:

  • 这只是 C# 8 中引入的语法糖
  • await using 适用于任何实现 IAsyncDisposable 的东西,它允许它有一个异步的 dispose 方法。
  • @Çöđěxěŕ 你是对的,这是使用异步一次性用品,也在 c# 8 中引入
  • @DetectivePikachu 当然是,但它们是两个不同的东西。第一个不会异步释放资源,第二个当然会,并且对 OP 更好;它使消费者能够在不阻塞主线程的情况下处理操作。
  • 我说你是对的,你还需要什么?

标签: async-await resharper using c#-8.0


【解决方案1】:

当您接受该建议时,发生了两件事:

  1. await using,可用于实现新 IAsyncDisposable 的类型。它与普通的using 相同,只是它调用DisposeAsync() 而不是Dispose()

  2. using 块更改为仅声明。此建议只是为了尽量减少代码中的嵌套。一旦对象超出范围,就会调用Dispose()/DisposeAsync()。你可以在the documentation阅读更多相关信息。

这是两个独立的功能,您可以彼此独立使用(您可以将await using 与块一起使用,或将using 用作语句),但两者在语言中都是全新的。

【讨论】:

  • 感谢您的回答,在什么情况下我们更喜欢其中一种?
  • 尽可能使用await using(您不能总是使用 - 这取决于对象是IDisposable 还是IAsyncDisposable)。要了解异步编程的好处,您可以阅读文档hereusing 语句与块实际上只是偏好。当你想控制对象的scope 时,你可能更喜欢一个块。
  • 谢谢加布里埃尔·卢奇!
【解决方案2】:

C# 8.0 引入了一些语法糖:

https://docs.microsoft.com/en-us/dotnet/csharp/whats-new/csharp-8#using-declarations

如果您在声明限制范围的变量(var responseReader 的 try 块)中应用 using,则该范围将用作 using 的边界。

它真正做的就是让你跳过写几个括号。但是它们仍然会在编译后的代码中。这使整个内容更具可读性。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2010-10-12
    • 1970-01-01
    • 2021-01-08
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-06-29
    • 2013-10-25
    相关资源
    最近更新 更多