CA1835: Föredrar minnesbaserade överlagringar av ReadAsync/WriteAsync-metoder i strömbaserade klasser
Property | Värde |
---|---|
Typnamn | PreferStreamAsyncMemoryOverloads |
Regel-ID | CA1835 |
Title | Föredrar minnesbaserade överlagringar av ReadAsync/WriteAsync-metoder i strömbaserade klasser |
Kategori | Prestanda |
Korrigeringen är icke-bakåtkompatibel | Icke-icke-bryta |
Aktiverad som standard i .NET 9 | Som förslag |
Orsak
Den här regeln letar upp väntande anrop av bytematrisbaserade metodöverlagringar för ReadAsync
och WriteAsync
, och föreslår att du använder minnesbaserade metodöverlagringar i stället, eftersom de är mer effektiva.
Regelbeskrivning
Minnesbaserade metodöverlagringar har en effektivare minnesanvändning än bytematrisbaserade.
Regeln fungerar på ReadAsync
och WriteAsync
anrop för alla klasser som ärver från Stream.
Regeln fungerar bara när metoden föregås av nyckelordet await
.
Identifierad metod | Föreslagen metod |
---|---|
ReadAsync(Byte[], Int32, Int32, CancellationToken) | ReadAsync(Memory<Byte>, CancellationToken) |
ReadAsync(Byte[], Int32, Int32) | ReadAsync(Memory<Byte>, CancellationToken) med CancellationToken inställt på default i C# eller Nothing i Visual Basic. |
WriteAsync(Byte[], Int32, Int32, CancellationToken) | WriteAsync(ReadOnlyMemory<Byte>, CancellationToken) |
WriteAsync(Byte[], Int32, Int32) | WriteAsync(ReadOnlyMemory<Byte>, CancellationToken) med CancellationToken inställt på default i C# eller Nothing i Visual Basic. |
Viktigt!
Se till att skicka heltalsargumenten offset
och count
till de skapade Memory
eller ReadOnlyMemory
instanserna.
Kommentar
Regel CA1835 är tillgänglig i alla .NET-versioner där minnesbaserade överlagringar är tillgängliga:
- .NET Standard 2.1 och senare.
- .NET Core 2.1 och senare.
Så här åtgärdar du överträdelser
Du kan antingen åtgärda dem manuellt, eller så kan du välja att låta Visual Studio göra det åt dig genom att hovra över glödlampan som visas bredvid metodanropet och välja den föreslagna ändringen. Exempel:
Regeln kan identifiera en mängd olika överträdelser för ReadAsync
metoderna och WriteAsync
. Här är exempel på de fall som regeln kan identifiera:
Exempel 1
Anrop av ReadAsync
, utan och med ett CancellationToken
argument:
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);
}
}
}
Lösningen
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);
}
}
}
Exempel 2
Anrop av WriteAsync
, utan och med ett CancellationToken
argument:
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);
}
}
}
Lösningen
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);
}
}
}
Exempel 3
Anrop med 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);
}
}
}
Lösningen
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);
}
}
}
Icke-överträdelser
Här följer några exempel på anrop där regeln inte utlöses.
Returvärdet sparas i en Task
variabel i stället för att inväntas:
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);
}
}
}
Returvärdet returneras av omslutningsmetoden i stället för att inväntas:
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);
}
}
Returvärdet används för att anropa ContinueWith
, vilket är den metod som väntar:
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 => { /* ... */ });
}
}
}
När du ska ignorera varningar
Det är säkert att förhindra en överträdelse av den här regeln om du inte bryr dig om att förbättra prestanda vid läsning eller skrivning av buffertar i strömbaserade klasser.
Ignorera en varning
Om du bara vill förhindra en enda överträdelse lägger du till förprocessordirektiv i källfilen för att inaktivera och aktiverar sedan regeln igen.
#pragma warning disable CA1835
// The code that's violating the rule is on this line.
#pragma warning restore CA1835
Om du vill inaktivera regeln för en fil, mapp eller ett projekt anger du dess allvarlighetsgrad till none
i konfigurationsfilen.
[*.{cs,vb}]
dotnet_diagnostic.CA1835.severity = none
Mer information finns i Så här utelämnar du kodanalysvarningar.