CA1835: Bevorzugen von arbeitsspeicherbasierten Überladungen von ReadAsync-/WriteAsync-Methoden in streambasierten Klassen
Eigenschaft | Wert |
---|---|
Typname | PreferStreamAsyncMemoryOverloads |
Regel-ID | CA1835 |
Titel | Bevorzugen von arbeitsspeicherbasierten Überladungen von ReadAsync-/WriteAsync-Methoden in streambasierten Klassen |
Kategorie | Leistung |
Fix führt oder führt nicht zur Unterbrechung | Nicht unterbrechend |
Standardmäßig in .NET 8 aktiviert | Als Vorschlag |
Ursache
Diese Regel sucht nach erwarteten Aufrufen der Bytearray-basierten Methodenüberladungen für ReadAsync
und WriteAsync
und schlägt vor, stattdessen die arbeitsspeicherbasierten Methodenüberladungen zu verwenden, da diese effizienter sind.
Regelbeschreibung
Die arbeitsspeicherbasierten Methodenüberladungen weisen eine effizientere Arbeitsspeicherauslastung als die Bytearray-basierten Überlastungen auf.
Die Regel funktioniert für ReadAsync
- und WriteAsync
-Aufrufe einer beliebigen Klasse, die von Stream erbt.
Die Regel funktioniert nur, wenn der Methode das Schlüsselwort await
vorangestellt ist.
Erkannte Methode | Vorgeschlagene Methode |
---|---|
ReadAsync(Byte[], Int32, Int32, CancellationToken) | ReadAsync(Memory<Byte>, CancellationToken) |
ReadAsync(Byte[], Int32, Int32) | ReadAsync(Memory<Byte>, CancellationToken), wobei CancellationToken in C# auf default und in Visual Basic auf Nothing festgelegt ist |
WriteAsync(Byte[], Int32, Int32, CancellationToken) | WriteAsync(ReadOnlyMemory<Byte>, CancellationToken) |
WriteAsync(Byte[], Int32, Int32) | WriteAsync(ReadOnlyMemory<Byte>, CancellationToken), wobei CancellationToken in C# auf default und in Visual Basic auf Nothing festgelegt ist |
Wichtig
Achten Sie darauf, das offset
-Argument und das ganzzahlige count
-Argument an die erstellte Memory
- oder ReadOnlyMemory
-Instanz zu übergeben
Hinweis
Die Regel CA1835 ist in allen .NET-Versionen verfügbar, in denen die arbeitsspeicherbasierte Überladungen verfügbar sind:
- .NET Standard 2.1 und höher
- .NET Core 2.1 und höher
Behandeln von Verstößen
Sie können Verstöße entweder manuell beheben oder dies Visual Studio überlassen. Sie müssen nur mit dem Mauszeiger auf die Glühbirne neben dem Methodenaufruf zeigen und die vorgeschlagene Änderung auswählen. Beispiel:
Die Regel kann eine Vielzahl von Verstößen gegen die Methoden ReadAsync
und WriteAsync
erkennen. Im Folgenden finden Sie einige Beispiele für die Fälle, die die Regel erkennen kann:
Beispiel 1
Aufrufe von ReadAsync
, mit und ohne 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);
}
}
}
Behebung:
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);
}
}
}
Beispiel 2
Aufrufe von WriteAsync
, mit und ohne 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);
}
}
}
Behebung:
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);
}
}
}
Beispiel 3
Aufrufe mit 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);
}
}
}
Behebung:
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);
}
}
}
Fälle, die keinen Verstoß darstellen
Im Folgenden finden Sie einige Beispiele für Aufrufe, bei denen die Regel nicht ausgelöst wird.
Der Rückgabewert wird in einer Task
-Variablen gespeichert, nicht abgewartet:
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);
}
}
}
Der Rückgabewert wird von der umschließenden Methode zurückgegeben, nicht abgewartet:
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);
}
}
Mit dem Rückgabewert wird ContinueWith
aufgerufen, wobei es sich um die erwartete Methode handelt:
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 => { /* ... */ });
}
}
}
Wann sollten Warnungen unterdrückt werden?
Verstöße gegen diese Regel können bedenkenlos unterdrückt werden, wenn Sie keine Bedenken hinsichtlich der Verbesserung der Leistung beim Lesen oder Schreiben aus bzw. in Puffer in streambasierten Klassen haben.
Unterdrücken einer Warnung
Um nur eine einzelne Verletzung zu unterdrücken, fügen Sie der Quelldatei Präprozessoranweisungen hinzu, um die Regel zu deaktivieren und dann wieder zu aktivieren.
#pragma warning disable CA1835
// The code that's violating the rule is on this line.
#pragma warning restore CA1835
Um die Regel für eine Datei, einen Ordner oder ein Projekt zu deaktivieren, legen Sie den Schweregrad in der Konfigurationsdatei auf none
fest.
[*.{cs,vb}]
dotnet_diagnostic.CA1835.severity = none
Weitere Informationen finden Sie unter Vorgehensweise: Unterdrücken von Codeanalyse-Warnungen.