Anteckning
Åtkomst till den här sidan kräver auktorisering. Du kan prova att logga in eller ändra kataloger.
Åtkomst till den här sidan kräver auktorisering. Du kan prova att ändra kataloger.
| Property | Värde | 
|---|---|
| Regel-ID | CA1844 | 
| Title | Ange minnesbaserade åsidosättningar av asynkrona metoder vid underklassificering av "Stream" | 
| Kategori | Prestanda | 
| Korrigeringen är icke-bakåtkompatibel | Icke-icke-bryta | 
| Aktiverad som standard i .NET 9 | Som förslag | 
Orsak
En typ som härleds från Stream åsidosättningar men åsidosätter ReadAsync(Byte[], Int32, Int32, CancellationToken)ReadAsync(Memory<Byte>, CancellationToken)inte . Eller en typ som härleds från Stream åsidosättningar men inte åsidosätter WriteAsync(Byte[], Int32, Int32, CancellationToken)WriteAsync(ReadOnlyMemory<Byte>, CancellationToken).
Regelbeskrivning
De minnesbaserade ReadAsync metoderna och WriteAsync metoderna har lagts till för att förbättra prestandan, vilket de åstadkommer på flera sätt:
- De återvänder ValueTaskochValueTask<int>i ställetTaskför ochTask<int>, respektive.
- De gör att alla typer av buffertar kan skickas in utan att behöva utföra en extra kopia till en matris.
För att uppnå dessa prestandafördelar måste typer som härleds från Stream tillhandahålla en egen minnesbaserad implementering. Annars tvingas standardimplementeringen att kopiera minnet till en matris för att anropa den matrisbaserade implementeringen, vilket resulterar i lägre prestanda. När anroparen skickar en eller Memory<T> en ReadOnlyMemory<T> instans som inte backas upp av en matris påverkas prestandan mer.
Så här åtgärdar du överträdelser
Det enklaste sättet att åtgärda överträdelser är att skriva om din matrisbaserade implementering som en minnesbaserad implementering och sedan implementera de matrisbaserade metoderna när det gäller minnesbaserade metoder.
Example
// This class violates the rule.
public class BadStream : Stream
{
    private readonly Stream _innerStream;
    public BadStream(Stream innerStream)
    {
        _innerStream = innerStream;
    }
    public override bool CanRead => _innerStream.CanRead;
    public override bool CanSeek => _innerStream.CanSeek;
    public override bool CanWrite => _innerStream.CanWrite;
    public override long Length => _innerStream.Length;
    public override long Position { get => _innerStream.Position; set => _innerStream.Position = value; }
    public override async Task<int> ReadAsync(byte[] buffer, int offset, int count, CancellationToken cancellationToken)
    {
        // ...
        return await _innerStream.ReadAsync(buffer, offset, count, cancellationToken);
    }
    public override async Task WriteAsync(byte[] buffer, int offset, int count, CancellationToken cancellationToken)
    {
        // ...
        await _innerStream.WriteAsync(buffer, offset, count, cancellationToken);
    }
    // Other required overrides
    public override void Flush() => _innerStream.Flush();
    public override int Read(byte[] buffer, int offset, int count) => _innerStream.Read(buffer, offset, count);
    public override long Seek(long offset, SeekOrigin origin) => _innerStream.Seek(offset, origin);
    public override void SetLength(long value) => _innerStream.SetLength(value);
    public override void Write(byte[] buffer, int offset, int count) => _innerStream.Write(buffer, offset, count);
}
// This class satisfies the rule.
public class GoodStream : Stream
{
    private readonly Stream _innerStream;
    public GoodStream(Stream innerStream)
    {
        _innerStream = innerStream;
    }
    public override bool CanRead => _innerStream.CanRead;
    public override bool CanSeek => _innerStream.CanSeek;
    public override bool CanWrite => _innerStream.CanWrite;
    public override long Length => _innerStream.Length;
    public override long Position { get => _innerStream.Position; set => _innerStream.Position = value; }
    public override async ValueTask<int> ReadAsync(Memory<byte> buffer, CancellationToken cancellationToken = default)
    {
        // ...
        return await _innerStream.ReadAsync(buffer, cancellationToken);
    }
    public override async ValueTask WriteAsync(ReadOnlyMemory<byte> buffer, CancellationToken cancellationToken = default)
    {
        // ...
        await _innerStream.WriteAsync(buffer, cancellationToken);
    }
    public override async Task<int> ReadAsync(byte[] buffer, int offset, int count, CancellationToken cancellationToken)
    {
        return await this.ReadAsync(buffer.AsMemory(offset, count), cancellationToken);
    }
    public override async Task WriteAsync(byte[] buffer, int offset, int count, CancellationToken cancellationToken)
    {
        await this.WriteAsync(buffer.AsMemory(offset, count), cancellationToken);
    }
    // Other required overrides
    public override void Flush() => _innerStream.Flush();
    public override int Read(byte[] buffer, int offset, int count) => _innerStream.Read(buffer, offset, count);
    public override long Seek(long offset, SeekOrigin origin) => _innerStream.Seek(offset, origin);
    public override void SetLength(long value) => _innerStream.SetLength(value);
    public override void Write(byte[] buffer, int offset, int count) => _innerStream.Write(buffer, offset, count);
}
När du ska ignorera varningar
Det är säkert att ignorera en varning från den här regeln om någon av följande situationer gäller:
- Prestandaträffen är inte ett problem.
- Du vet att underklassen Streambara kommer att använda matrisbaserade metoder.
- Underklassen Streamhar beroenden som inte stöder minnesbaserade buffertar.
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 CA1844
// The code that's violating the rule is on this line.
#pragma warning restore CA1844
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.CA1844.severity = none
Mer information finns i Så här utelämnar du kodanalysvarningar.