CA1835: Upřednostněte přetížení využívající paměť metod ReadAsync/WriteAsync v třídách založených na proudu

Vlastnost Hodnota
Název typu PreferStreamAsyncMemoryOverloads
ID pravidla CA1835
Název Upřednostněte paměťově založená přetížení těchto metod ReadAsync/WriteAsync v třídách na bázi proudu.
Kategorie Výkon
Oprava, která může být destruktivní nebo nedestruktivní Nezlomitelný
Povoleno ve výchozím nastavení v .NET 10 Jako návrh
Příslušné jazyky C# a Visual Basic

Příčina

Toto pravidlo vyhledá očekávané vyvolání přetížení metody založené na poli bajtů pro ReadAsync a WriteAsync a navrhuje použití přetížení metody založené na paměti, protože jsou efektivnější.

Popis pravidla

Přetížení metod založených na paměti využívají paměť efektivněji než ty na bázi byte array.

Pravidlo funguje pro ReadAsync a WriteAsync vyvolání jakékoli třídy, která dědí z Stream.

Pravidlo funguje pouze v případech, kdy je před metodou await klíčové slovo.

Zjištěná metoda Navrhovaná metoda
ReadAsync(Byte[], Int32, Int32, CancellationToken) ReadAsync(Memory<Byte>, CancellationToken)
ReadAsync(Byte[], Int32, Int32) ReadAsync(Memory<Byte>, CancellationToken) s CancellationToken nastaveno na default v jazyce C# nebo Nothing v jazyce Visual Basic.
WriteAsync(Byte[], Int32, Int32, CancellationToken) WriteAsync(ReadOnlyMemory<Byte>, CancellationToken)
WriteAsync(Byte[], Int32, Int32) s WriteAsync(ReadOnlyMemory<Byte>, CancellationToken) ve CancellationToken nastaveným na default v jazyce C# nebo Nothing v jazyce Visual Basic.

Důležité

Nezapomeňte do vytvořených offset nebo count instancí předat MemoryReadOnlyMemory celočíselné argumenty.

Poznámka:

Pravidlo CA1835 je k dispozici ve všech verzích .NET, kde jsou k dispozici přetížení založená na paměti:

  • .NET Standard 2.1 a novější.
  • .NET Core 2.1 a novější.

Jak opravit porušení

Můžete je opravit ručně, nebo se můžete rozhodnout, že to visual Studio udělá za vás, když najedete myší na žárovku, která se zobrazí vedle vyvolání metody, a výběrem navrhované změny. Příklad:

Oprava kódu pro CA1835 – upřednostňujte přetížení na základě paměti metod ReadAsync/WriteAsync ve třídách založených na datových proudech.

Toto pravidlo může detekovat různá porušení pravidel ReadAsync a WriteAsync metod. Tady jsou příklady případů, které pravidlo dokáže rozpoznat:

Příklad 1

Invokace ReadAsync, bez a s 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);
        }
    }
}

Opravit:

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

Příklad 2

Vyvolání WriteAsyncfunkce , bez a s 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);
        }
    }
}

Opravit:

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

Příklad 3

Vyvolání s 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);
        }
    }
}

Opravit:

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

Nenarušení

Následuje několik příkladů vyvolání, kdy se pravidlo neaktivuje .

Vrácená hodnota je uložena v Task proměnné místo toho, aby byla očekávána:

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

Návratová hodnota je vrácena metodou wrapping namísto očekávání:

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

Návratová hodnota se používá k volání ContinueWith, což je metoda, která se očekává:

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 => { /* ... */ });
        }
    }
}

Kdy potlačit upozornění

Je bezpečné potlačit porušení tohoto pravidla, pokud vás nezajímá zlepšení výkonu při čtení nebo zápisu do bufferů ve třídách využívajících datové proudy.

Potlačení upozornění

Pokud chcete pouze potlačit jedno porušení, přidejte do zdrojového souboru direktivy preprocesoru, abyste pravidlo zakázali a znovu povolili.

#pragma warning disable CA1835
// The code that's violating the rule is on this line.
#pragma warning restore CA1835

Pokud chcete pravidlo pro soubor, složku nebo projekt zakázat, nastavte jeho závažnost v none konfiguračním souboru.

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

Další informace naleznete v tématu Jak potlačit upozornění analýzy kódu.

Viz také