Hinweis
Für den Zugriff auf diese Seite ist eine Autorisierung erforderlich. Sie können versuchen, sich anzumelden oder das Verzeichnis zu wechseln.
Für den Zugriff auf diese Seite ist eine Autorisierung erforderlich. Sie können versuchen, das Verzeichnis zu wechseln.
| Eigenschaft | Wert |
|---|---|
| Regel-ID | CA1844 |
| Titel | Arbeitsspeicherbasierte asynchrone Methoden beim Erstellen von Unterklassen von „Stream“ außer Kraft setzen |
| Kategorie | Leistung |
| Fix führt oder führt nicht zur Unterbrechung | Nicht unterbrechend |
| Standardmäßig in .NET 10 aktiviert | Als Vorschlag |
Ursache
Ein von Stream abgeleiteter Typ überschreibt ReadAsync(Byte[], Int32, Int32, CancellationToken), aber nicht ReadAsync(Memory<Byte>, CancellationToken). Oder ein von Stream abgeleiteter Typ überschreibt WriteAsync(Byte[], Int32, Int32, CancellationToken), aber nicht WriteAsync(ReadOnlyMemory<Byte>, CancellationToken).
Regelbeschreibung
Die speicherbasierten Methoden ReadAsync und WriteAsync wurden hinzugefügt, um die Leistung zu verbessern. Dies wird von ihnen auf verschiedene Weise erreicht:
- Sie geben
ValueTaskbzw.ValueTask<int>anstelle vonTaskbzw.Task<int>zurück. - Sie ermöglichen das Übergeben beliebiger Puffertypen, ohne dass eine zusätzliche Kopie in ein Array erfolgen muss.
Um diese Leistungsvorteile zu nutzen, müssen von Stream abgeleitete Typen eine eigene speicherbasierte Implementierung bereitstellen. Andernfalls wird die Standardimplementierung gezwungen, den Arbeitsspeicher in ein Array zu kopieren, um die arraybasierte Implementierung aufzurufen, was zu einer verringerten Leistung führt. Wenn der Aufrufer eine Memory<T>- oder ReadOnlyMemory<T>-Instanz übergibt, die nicht von einem Array unterstützt wird, wird die Leistung stärker beeinträchtigt.
Behandeln von Verstößen
Die einfachste Möglichkeit zum Beheben von Verstößen besteht darin, die arraybasierte Implementierung in eine speicherbasierte Implementierung umzuschreiben und die arraybasierten Methoden anschließend in Bezug auf die speicherbasierten Methoden zu implementieren.
Example
// This class violates the rule.
public class BadStream : Stream
{
private readonly Stream _innerStream;
public BadStream(Stream innerStream)
{
_innerStream = innerStream;
}
public override bool CanRead => _innerStream.CanRead;
public override bool CanSeek => _innerStream.CanSeek;
public override bool CanWrite => _innerStream.CanWrite;
public override long Length => _innerStream.Length;
public override long Position { get => _innerStream.Position; set => _innerStream.Position = value; }
public override async Task<int> ReadAsync(byte[] buffer, int offset, int count, CancellationToken cancellationToken)
{
// ...
return await _innerStream.ReadAsync(buffer, offset, count, cancellationToken);
}
public override async Task WriteAsync(byte[] buffer, int offset, int count, CancellationToken cancellationToken)
{
// ...
await _innerStream.WriteAsync(buffer, offset, count, cancellationToken);
}
// Other required overrides
public override void Flush() => _innerStream.Flush();
public override int Read(byte[] buffer, int offset, int count) => _innerStream.Read(buffer, offset, count);
public override long Seek(long offset, SeekOrigin origin) => _innerStream.Seek(offset, origin);
public override void SetLength(long value) => _innerStream.SetLength(value);
public override void Write(byte[] buffer, int offset, int count) => _innerStream.Write(buffer, offset, count);
}
// This class satisfies the rule.
public class GoodStream : Stream
{
private readonly Stream _innerStream;
public GoodStream(Stream innerStream)
{
_innerStream = innerStream;
}
public override bool CanRead => _innerStream.CanRead;
public override bool CanSeek => _innerStream.CanSeek;
public override bool CanWrite => _innerStream.CanWrite;
public override long Length => _innerStream.Length;
public override long Position { get => _innerStream.Position; set => _innerStream.Position = value; }
public override async ValueTask<int> ReadAsync(Memory<byte> buffer, CancellationToken cancellationToken = default)
{
// ...
return await _innerStream.ReadAsync(buffer, cancellationToken);
}
public override async ValueTask WriteAsync(ReadOnlyMemory<byte> buffer, CancellationToken cancellationToken = default)
{
// ...
await _innerStream.WriteAsync(buffer, cancellationToken);
}
public override async Task<int> ReadAsync(byte[] buffer, int offset, int count, CancellationToken cancellationToken)
{
return await this.ReadAsync(buffer.AsMemory(offset, count), cancellationToken);
}
public override async Task WriteAsync(byte[] buffer, int offset, int count, CancellationToken cancellationToken)
{
await this.WriteAsync(buffer.AsMemory(offset, count), cancellationToken);
}
// Other required overrides
public override void Flush() => _innerStream.Flush();
public override int Read(byte[] buffer, int offset, int count) => _innerStream.Read(buffer, offset, count);
public override long Seek(long offset, SeekOrigin origin) => _innerStream.Seek(offset, origin);
public override void SetLength(long value) => _innerStream.SetLength(value);
public override void Write(byte[] buffer, int offset, int count) => _innerStream.Write(buffer, offset, count);
}
Wann sollten Warnungen unterdrückt werden?
In den folgenden Situationen ist es sicher, eine Warnung aus dieser Regel zu unterdrücken:
- Leistungseinbußen sind kein Problem.
- Sie wissen, dass Ihre
Stream-Unterklasse grundsätzlich nur die arraybasierten Methoden verwendet. - Ihre
Stream-Unterklasse verfügt über Abhängigkeiten, die keine speicherbasierten Puffer unterstützen.
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 CA1844
// The code that's violating the rule is on this line.
#pragma warning restore CA1844
Um die Regel für eine Datei, einen Ordner oder ein Projekt zu deaktivieren, legen Sie den Schweregrad in der none auf fest.
[*.{cs,vb}]
dotnet_diagnostic.CA1844.severity = none
Weitere Informationen finden Sie unter Vorgehensweise: Unterdrücken von Codeanalyse-Warnungen.