Freigeben über


CA1835: Bevorzugen Sie die speicherbasierten Überladungen der Methoden ReadAsync/WriteAsync in streambasierten Klassen

Eigenschaft Wert
Typname PreferStreamAsyncMemoryOverloads
Regel-ID CA1835
Titel Bevorzugen Sie arbeitsspeicherbasierte Überladungen von Methoden wie ReadAsync/WriteAsync in streambasierten Klassen.
Kategorie Leistung
Fix führt zu Unterbrechungen oder bleibt funktionsfähig Untrennbar
Standardmäßig in .NET 10 aktiviert Als Vorschlag
Anwendbare Sprachen C# und Visual Basic

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, sofern die speicherbasierten Überladungen verfügbar sind.

  • .NET Standard 2.1 und höher
  • .NET Core 2.1 und höher

So beheben Sie Verstöße

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:

Codefix für CA1835: Bevorzugen von arbeitsspeicherbasierten Überladungen von ReadAsync-/WriteAsync-Methoden in streambasierten Klassen

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, ohne und mit einem 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, ohne und mit einem 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);
        }
    }
}

Korrektur:

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);
        }
    }
}

Keine Verstöße

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 auf none in der Konfigurationsdatei fest.

[*.{cs,vb}]
dotnet_diagnostic.CA1835.severity = none

Weitere Informationen finden Sie unter Vorgehensweise: Unterdrücken von Codeanalyse-Warnungen.

Siehe auch