前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >CA1835:在基于流的类中,首选 ReadAsync/WriteAsync 方法的基于内存的重载

CA1835:在基于流的类中,首选 ReadAsync/WriteAsync 方法的基于内存的重载

作者头像
用户4268038
发布2022-02-19 18:54:13
1.1K0
发布2022-02-19 18:54:13
举报
文章被收录于专栏:stcnbstcnb

类型名称

PreferStreamAsyncMemoryOverloads

规则 ID

CA1835

类别

“性能”

修复是中断修复还是非中断修复

非中断

原因

此规则查找 ReadAsync 和 WriteAsync 的基于字节数组的方法重载的等待调用,并建议改为使用基于内存的方法重载,因为它们的效率更高。

规则说明

基于内存的方法重载具有比基于字节数组的重载更有效的内存使用。

此规则适用于从 Stream 继承的任何类的 ReadAsync 和 WriteAsync 调用。

仅当方法前面带有 await 关键字时,此规则才有效。

检测到的方法

建议的方法

ReadAsync(Byte[], Int32, Int32, CancellationToken)

ReadAsync(Memory<Byte>, CancellationToken)

ReadAsync(Byte[], Int32, Int32)

CancellationToken 设置为 default(在 C# 中)或 Nothing(在 Visual Basic 中)的 ReadAsync(Memory<Byte>, CancellationToken)。

WriteAsync(Byte[], Int32, Int32, CancellationToken)

WriteAsync(ReadOnlyMemory<Byte>, CancellationToken)

WriteAsync(Byte[], Int32, Int32)

CancellationToken 设置为 default(在 C# 中)或 Nothing(在 Visual Basic 中)的 WriteAsync(ReadOnlyMemory<Byte>, CancellationToken)。

重要

确保将 offset 和 count 整数参数传递到创建的 Memory 或 ReadOnlyMemory 实例。

备注

规则 CA1835 适用于所有提供基于内存的重载的 .NET 版本:

.NET Standard 2.1 及更高版本。

.NET Core 2.1 及更高版本。

如何解决冲突

可以手动修复,也可以选择让 Visual Studio 执行修复,方法是将鼠标悬停在方法调用旁显示的灯泡图标上,然后选择建议的更改。 示例:

此规则可以检测 ReadAsync 和 WriteAsync 方法的多种冲突。 下面是此规则可检测到的情况示例:

示例 1

ReadAsync 的调用,未使用和使用 CancellationToken 参数:

using System;

using System.IO;

using System.Threading;

class MyClass

{

public async void MyMethod(CancellationToken ct)

{

using (FileStream s = new FileStream("path.txt", FileMode.Create))

{

byte[] buffer = new byte[s.Length];

await s.ReadAsync(buffer, 0, buffer.Length);

await s.ReadAsync(buffer, 0, buffer.Length, ct);

}

}

}

解决方法:

using System;

using System.IO;

using System.Threading;

class MyClass

{

public async void MyMethod(CancellationToken ct)

{

using (FileStream s = new FileStream("path.txt", FileMode.Create))

{

byte[] buffer = new byte[s.Length];

await s.ReadAsync(buffer.AsMemory(0, buffer.Length));

await s.ReadAsync(buffer.AsMemory(0, buffer.Length), ct);

}

}

}

示例 2

WriteAsync 的调用,未使用和使用 CancellationToken 参数:

using System;

using System.IO;

using System.Threading;

class MyClass

{

public async void MyMethod(CancellationToken ct)

{

using (FileStream s = File.Open("path.txt", FileMode.Open))

{

byte[] buffer = { 0xBA, 0x5E, 0xBA, 0x11, 0xF0, 0x07, 0xBA, 0x11 };

await s.WriteAsync(buffer, 0, buffer.Length);

await s.WriteAsync(buffer, 0, buffer.Length, ct);

}

}

}

解决方法:

using System;

using System.IO;

using System.Threading;

class MyClass

{

public async void MyMethod()

{

using (FileStream s = File.Open("path.txt", FileMode.Open))

{

byte[] buffer = { 0xBA, 0x5E, 0xBA, 0x11, 0xF0, 0x07, 0xBA, 0x11 };

await s.WriteAsync(buffer.AsMemory(0, buffer.Length));

await s.WriteAsync(buffer.AsMemory(0, buffer.Length), ct);

}

}

}

示例 3

使用 ConfigureAwait 的调用:

using System;

using System.IO;

using System.Threading;

class MyClass

{

public async void MyMethod()

{

using (FileStream s = File.Open("path.txt", FileMode.Open))

{

byte[] buffer1 = { 0xBA, 0x5E, 0xBA, 0x11, 0xF0, 0x07, 0xBA, 0x11 };

await s.WriteAsync(buffer1, 0, buffer1.Length).ConfigureAwait(false);

byte[] buffer2 = new byte[s.Length];

await s.ReadAsync(buffer2, 0, buffer2.Length).ConfigureAwait(true);

}

}

}

解决方法:

using System;

using System.IO;

using System.Threading;

class MyClass

{

public async void MyMethod()

{

using (FileStream s = File.Open("path.txt", FileMode.Open))

{

byte[] buffer1 = { 0xBA, 0x5E, 0xBA, 0x11, 0xF0, 0x07, 0xBA, 0x11 };

await s.WriteAsync(buffer1.AsMemory(0, buffer1.Length)).ConfigureAwait(false);

byte[] buffer2 = new byte[s.Length];

await s.ReadAsync(buffer2.AsMemory(0, buffer.Length)).ConfigureAwait(true);

}

}

}

无冲突

下面是不会触发此规则的一些调用示例。

返回值保存在 Task 变量中,而不是在等待:

using System;

using System.IO;

using System.Threading;

using System.Threading.Tasks;

class MyClass

{

public void MyMethod()

{

byte[] buffer = { 0xBA, 0x5E, 0xBA, 0x11, 0xF0, 0x07, 0xBA, 0x11 };

using (FileStream s = new FileStream("path.txt", FileMode.Create))

{

Task t = s.WriteAsync(buffer, 0, buffer.Length);

}

}

}

返回值由包装方法返回,而不是在等待:

using System;

using System.IO;

using System.Threading;

using System.Threading.Tasks;

class MyClass

{

public Task MyMethod(FileStream s, byte[] buffer)

{

return s.WriteAsync(buffer, 0, buffer.Length);

}

}

返回值用于调用 ContinueWith,这是在等待的方法:

using System;

using System.IO;

using System.Threading;

using System.Threading.Tasks;

class MyClass

{

public void MyMethod()

{

byte[] buffer = { 0xBA, 0x5E, 0xBA, 0x11, 0xF0, 0x07, 0xBA, 0x11 };

using (FileStream s = new FileStream("path.txt", FileMode.Create))

{

await s.WriteAsync(buffer, 0, buffer.Length).ContinueWith(c => { /* ... */ });

}

}

}

何时禁止显示警告

如果不考虑在基于流的类中读取或写入缓冲区时提高性能,则可以放心地抑制此规则的冲突。

另请参阅

性能规则

本文系外文翻译,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文系外文翻译前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档