值
类型名称
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 删除。