CA1835: Preferisce gli overload basati sulla memoria dei metodi ReadAsync/WriteAsync nelle classi basate su flusso

Proprietà valore
Nome tipo PreferStreamAsyncMemoryOverloads
ID regola CA1835
Title Preferisce gli overload basati sulla memoria dei metodi ReadAsync/WriteAsync nelle classi basate su flusso
Categoria Prestazioni
Correzione che causa un'interruzione o un'interruzione Nessuna interruzione
Abilitato per impostazione predefinita in .NET 8 Come suggerimento

Causa

Questa regola individua le chiamate attese degli overload dei metodi basati su matrice di byte per ReadAsync e WriteAsynce suggerisce l'uso degli overload del metodo basato sulla memoria, perché sono più efficienti.

Descrizione regola

Gli overload dei metodi basati sulla memoria hanno un utilizzo di memoria più efficiente rispetto a quelli basati su matrice di byte.

La regola funziona su ReadAsync e WriteAsync chiamate di qualsiasi classe che eredita da Stream.

La regola funziona solo quando il metodo è preceduto dalla await parola chiave .

Metodo rilevato Metodo suggerito
ReadAsync(Byte[], Int32, Int32, CancellationToken) ReadAsync(Memory<Byte>, CancellationToken)
ReadAsync(Byte[], Int32, Int32) ReadAsync(Memory<Byte>, CancellationToken) con CancellationToken impostato su default in C# o Nothing in Visual Basic.
WriteAsync(Byte[], Int32, Int32, CancellationToken) WriteAsync(ReadOnlyMemory<Byte>, CancellationToken)
WriteAsync(Byte[], Int32, Int32) WriteAsync(ReadOnlyMemory<Byte>, CancellationToken) con CancellationToken impostato su default in C# o Nothing in Visual Basic.

Importante

Assicurarsi di passare gli offset argomenti e count integer alle istanze create Memory o ReadOnlyMemory .

Nota

La regola CA1835 è disponibile in tutte le versioni .NET in cui sono disponibili gli overload basati sulla memoria:

  • .NET Standard 2.1 e versioni successive.
  • .NET Core 2.1 e versioni successive.

Come correggere le violazioni

È possibile correggerli manualmente oppure scegliere di consentire a Visual Studio di farlo automaticamente, passando il mouse sulla lampadina visualizzata accanto alla chiamata al metodo e selezionando la modifica suggerita. Esempio:

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

La regola può rilevare un'ampia gamma di violazioni per i ReadAsync metodi e WriteAsync . Ecco alcuni esempi dei casi che la regola può rilevare:

Esempio 1

Chiamate di ReadAsync, senza e con un CancellationToken argomento:

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

Correzione:

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

Esempio 2

Chiamate di WriteAsync, senza e con un CancellationToken argomento:

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

Correzione:

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

Esempio 3

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

Correzione:

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

Violazioni non

Di seguito sono riportati alcuni esempi di chiamate in cui la regola non verrà attivata.

Il valore restituito viene salvato in una Task variabile anziché essere atteso:

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

Il valore restituito viene restituito dal metodo di wrapping anziché essere atteso:

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

Il valore restituito viene usato per chiamare ContinueWith, ovvero il metodo in attesa:

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

Quando eliminare gli avvisi

È possibile eliminare una violazione di questa regola se non si è preoccupati per migliorare le prestazioni durante la lettura o la scrittura di buffer nelle classi basate su flusso.

Eliminare un avviso

Se si vuole eliminare una singola violazione, aggiungere direttive del preprocessore al file di origine per disabilitare e quindi riabilitare la regola.

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

Per disabilitare la regola per un file, una cartella o un progetto, impostarne la gravità none su nel file di configurazione.

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

Per altre informazioni, vedere Come eliminare gli avvisi di analisi del codice.

Vedi anche