CA1835: Preferuj przeciążenia oparte na pamięci metod ReadAsync/WriteAsync w klasach opartych na strumieniu
Właściwości | Wartość |
---|---|
Nazwa typu | PreferStreamAsyncMemoryOverloads |
Identyfikator reguły | CA1835 |
Tytuł | Preferuj przeciążenia oparte na pamięci metod ReadAsync/WriteAsync w klasach opartych na strumieniu |
Kategoria | Wydajność |
Poprawka powodująca niezgodność lub niezgodność | Niezgodność |
Domyślnie włączone na platformie .NET 9 | Jako sugestia |
Przyczyna
Ta reguła lokalizuje oczekiwane wywołania przeciążeń metody opartej na tablicy bajtów dla ReadAsync
metod i WriteAsync
i i sugeruje użycie przeciążeń metody opartej na pamięci, ponieważ są one bardziej wydajne.
Opis reguły
Przeciążenia metody opartej na pamięci mają bardziej wydajne użycie pamięci niż te oparte na tablicy bajtów.
Reguła działa na ReadAsync
wywołaniach dowolnej klasy dziedziczonej z WriteAsync
klasy i Stream .
Reguła działa tylko wtedy, gdy metoda jest poprzedzona await
słowem kluczowym.
Wykryta metoda | Sugerowana metoda |
---|---|
ReadAsync(Byte[], Int32, Int32, CancellationToken) | ReadAsync(Memory<Byte>, CancellationToken) |
ReadAsync(Byte[], Int32, Int32) |
ReadAsync(Memory<Byte>, CancellationToken) z ustawioną wartością CancellationToken default w języku C#lub Nothing w Visual Basic. |
WriteAsync(Byte[], Int32, Int32, CancellationToken) | WriteAsync(ReadOnlyMemory<Byte>, CancellationToken) |
WriteAsync(Byte[], Int32, Int32) |
WriteAsync(ReadOnlyMemory<Byte>, CancellationToken) z ustawioną wartością CancellationToken default w języku C#lub Nothing w Visual Basic. |
Ważne
Pamiętaj, aby przekazać offset
argumenty i count
liczby całkowite do utworzonych Memory
wystąpień lub ReadOnlyMemory
.
Uwaga
Reguła CA1835 jest dostępna we wszystkich wersjach platformy .NET, w których dostępne są przeciążenia oparte na pamięci:
- .NET Standard 2.1 lub nowszy.
- .NET Core 2.1 lub nowszy.
Jak naprawić naruszenia
Możesz je naprawić ręcznie lub możesz zezwolić programowi Visual Studio na to zrobić, umieszczając wskaźnik myszy na żarówki, która jest wyświetlana obok wywołania metody i wybierając sugerowaną zmianę. Przykład:
Reguła może wykrywać różne naruszenia metod ReadAsync
i WriteAsync
. Oto przykłady przypadków, w których reguła może wykryć:
Przykład 1
Wywołania elementu , bez argumentu ReadAsync
i z argumentem 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);
}
}
}
Naprawa:
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);
}
}
}
Przykład 2
Wywołania elementu , bez argumentu WriteAsync
i z argumentem 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);
}
}
}
Naprawa:
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);
}
}
}
Przykład 3
Wywołania za pomocą polecenia 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);
}
}
}
Naprawa:
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);
}
}
}
Naruszenia niezwiązane z naruszeniem
Poniżej przedstawiono kilka przykładów wywołań, w których reguła nie zostanie wyzwolona.
Wartość zwracana jest zapisywana w zmiennej Task
, a nie oczekiwana:
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);
}
}
}
Zwracana jest wartość zwracana przez metodę opakowującego, a nie oczekiwaną:
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);
}
}
Wartość zwracana jest używana do wywołania ContinueWith
metody , która jest oczekiwana:
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 => { /* ... */ });
}
}
}
Kiedy pomijać ostrzeżenia
Można bezpiecznie pominąć naruszenie tej reguły, jeśli nie martwisz się o poprawę wydajności podczas odczytywania lub zapisywania w klasach opartych na strumieniu.
Pomijanie ostrzeżenia
Jeśli chcesz po prostu pominąć pojedyncze naruszenie, dodaj dyrektywy preprocesora do pliku źródłowego, aby wyłączyć, a następnie ponownie włączyć regułę.
#pragma warning disable CA1835
// The code that's violating the rule is on this line.
#pragma warning restore CA1835
Aby wyłączyć regułę dla pliku, folderu lub projektu, ustaw jego ważność na none
w pliku konfiguracji.
[*.{cs,vb}]
dotnet_diagnostic.CA1835.severity = none
Aby uzyskać więcej informacji, zobacz Jak pominąć ostrzeżenia dotyczące analizy kodu.