Share via


CA1835: Upřednostněte přetížení na základě paměti metod ReadAsync/WriteAsync v datových třídách

Vlastnost Hodnota
Název typu PreferStreamAsyncMemoryOverloads
ID pravidla CA1835
Název Upřednostněte přetížení metod ReadAsync/WriteAsync v datových třídách.
Kategorie Výkon
Oprava způsobující chybu nebo chybu způsobující chybu Nenarušující
Povoleno ve výchozím nastavení v .NET 8 Jako návrh

Příčina

Toto pravidlo vyhledá očekávané vyvolání přetížení metody založené na bajtech pole a ReadAsyncWriteAsyncnavrhuje použití přetížení metody založené na paměti místo toho, protože jsou efektivnější.

Popis pravidla

Přetížení metody založené na paměti mají efektivnější využití paměti než bajtové pole.

Pravidlo funguje na 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)default v CancellationToken jazyce C# nebo Nothing v jazyce Visual Basic.
WriteAsync(Byte[], Int32, Int32, CancellationToken) WriteAsync(ReadOnlyMemory<Byte>, CancellationToken)
WriteAsync(Byte[], Int32, Int32) WriteAsync(ReadOnlyMemory<Byte>, CancellationToken)default v CancellationToken jazyce C# nebo Nothing v jazyce Visual Basic.

Důležité

Nezapomeňte do vytvořených Memory nebo ReadOnlyMemory instancí předat offsetcount 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:

Code fix for CA1835 - Prefer the memory-based overloads of ReadAsync/WriteAsync methods in stream-based classes

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

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

Neresektování

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 vyrovnávacích pamětí ve třídách založených na datových proudech.

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é