Share via


CA1835: Föredrar minnesbaserade överlagringar av ReadAsync/WriteAsync-metoder i strömbaserade klasser

Property Värde
Typnamn PreferStreamAsyncMemoryOverloads
Regel-ID CA1835
Title Föredrar minnesbaserade överlagringar av ReadAsync/WriteAsync-metoder i strömbaserade klasser
Kategori Prestanda
Korrigeringen är icke-bakåtkompatibel Icke-icke-bryta
Aktiverad som standard i .NET 8 Som förslag

Orsak

Den här regeln letar upp väntande anrop av bytematrisbaserade metodöverlagringar för ReadAsync och WriteAsync, och föreslår att du använder minnesbaserade metodöverlagringar i stället, eftersom de är mer effektiva.

Regelbeskrivning

Minnesbaserade metodöverlagringar har en effektivare minnesanvändning än bytematrisbaserade.

Regeln fungerar på ReadAsync och WriteAsync anrop för alla klasser som ärver från Stream.

Regeln fungerar bara när metoden föregås av nyckelordet await .

Identifierad metod Föreslagen metod
ReadAsync(Byte[], Int32, Int32, CancellationToken) ReadAsync(Memory<Byte>, CancellationToken)
ReadAsync(Byte[], Int32, Int32) ReadAsync(Memory<Byte>, CancellationToken) med CancellationToken inställt på default i C# eller Nothing i Visual Basic.
WriteAsync(Byte[], Int32, Int32, CancellationToken) WriteAsync(ReadOnlyMemory<Byte>, CancellationToken)
WriteAsync(Byte[], Int32, Int32) WriteAsync(ReadOnlyMemory<Byte>, CancellationToken) med CancellationToken inställt på default i C# eller Nothing i Visual Basic.

Viktigt!

Se till att skicka heltalsargumenten offset och count till de skapade Memory eller ReadOnlyMemory instanserna.

Kommentar

Regel CA1835 är tillgänglig i alla .NET-versioner där minnesbaserade överlagringar är tillgängliga:

  • .NET Standard 2.1 och senare.
  • .NET Core 2.1 och senare.

Så här åtgärdar du överträdelser

Du kan antingen åtgärda dem manuellt, eller så kan du välja att låta Visual Studio göra det åt dig genom att hovra över glödlampan som visas bredvid metodanropet och välja den föreslagna ändringen. Exempel:

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

Regeln kan identifiera en mängd olika överträdelser för ReadAsync metoderna och WriteAsync . Här är exempel på de fall som regeln kan identifiera:

Exempel 1

Anrop av ReadAsync, utan och med ett 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);
        }
    }
}

Lösningen

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

Exempel 2

Anrop av WriteAsync, utan och med ett 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);
        }
    }
}

Lösningen

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

Exempel 3

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

Lösningen

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

Icke-överträdelser

Här följer några exempel på anrop där regeln inte utlöses.

Returvärdet sparas i en Task variabel i stället för att inväntas:

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

Returvärdet returneras av omslutningsmetoden i stället för att inväntas:

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

Returvärdet används för att anropa ContinueWith, vilket är den metod som väntar:

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

När du ska ignorera varningar

Det är säkert att förhindra en överträdelse av den här regeln om du inte bryr dig om att förbättra prestanda vid läsning eller skrivning av buffertar i strömbaserade klasser.

Ignorera en varning

Om du bara vill förhindra en enda överträdelse lägger du till förprocessordirektiv i källfilen för att inaktivera och aktiverar sedan regeln igen.

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

Om du vill inaktivera regeln för en fil, mapp eller ett projekt anger du dess allvarlighetsgrad till none i konfigurationsfilen.

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

Mer information finns i Så här utelämnar du kodanalysvarningar.

Se även