Ескертпе
Бұл бетке кіру үшін қатынас шегін айқындау қажет. Жүйеге кіруді немесе каталогтарды өзгертуді байқап көруге болады.
Бұл бетке кіру үшін қатынас шегін айқындау қажет. Каталогтарды өзгертуді байқап көруге болады.
| Свойство | Значение |
|---|---|
| Имя типа | PreferStreamAsyncMemoryOverloads |
| Идентификатор правила | CA1835 |
| Заголовок | Предпочитайте перегрузки на основе памяти методов ReadAsync/WriteAsync в классах на основе потоков |
| Категория | Производительность |
| Исправление является критическим или не критическим | неразрывный |
| Включен по умолчанию в .NET 10 | Как предложение |
| Применимые языки | C# и Visual Basic |
Причина
Это правило находит ожидаемые вызовы перегрузок метода, работающих с массивами байтов для ReadAsync и WriteAsync, и предлагает использовать перегрузки метода, работающие с памятью, так как они более эффективны.
Описание правила
Перегрузки методов, основанные на памяти, используют ее более эффективно, чем перегрузки, основанные на массивах байтов.
Правило работает с вызовами ReadAsync и WriteAsync любого класса, наследуемого от Stream.
Правило работает только в том случае, если перед методом стоит ключевое слово await.
| Обнаруженный метод | Предлагаемый метод |
|---|---|
| ReadAsync(Byte[], Int32, Int32, CancellationToken) | ReadAsync(Memory<Byte>, CancellationToken) |
| ReadAsync(Byte[], Int32, Int32) |
ReadAsync(Memory<Byte>, CancellationToken) с параметром CancellationToken, имеющим значение default в C# или Nothing в Visual Basic. |
| WriteAsync(Byte[], Int32, Int32, CancellationToken) | WriteAsync(ReadOnlyMemory<Byte>, CancellationToken) |
| WriteAsync(Byte[], Int32, Int32) |
WriteAsync(ReadOnlyMemory<Byte>, CancellationToken) с параметром CancellationToken, имеющим значение default в C# или Nothing в Visual Basic. |
Внимание
Не забудьте передать целочисленные аргументы 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 => { /* ... */ });
}
}
}
Когда лучше отключить предупреждения
Можно игнорировать нарушение этого правила, если вас не волнует улучшение производительности при чтении или записи буферов в классах потоковой передачи.
Отключение предупреждений
Если вы просто хотите отключить одно нарушение, добавьте директивы препроцессора в исходный файл, чтобы отключить и повторно включить правило.
#pragma warning disable CA1835
// The code that's violating the rule is on this line.
#pragma warning restore CA1835
Чтобы отключить правило для файла, папки или проекта, задайте его серьезность none в файле конфигурации.
[*.{cs,vb}]
dotnet_diagnostic.CA1835.severity = none
Дополнительные сведения см. в разделе Практическое руководство. Скрытие предупреждений анализа кода.