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 |
La correzione causa un'interruzione o meno | Non causa un'interruzione |
Abilitato per impostazione predefinita in .NET 9 | Come suggerimento |
Causa
Questa regola individua le chiamate attese degli overload dei metodi basati su matrice di byte per ReadAsync
e WriteAsync
e 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:
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.