| 屬性 | 值 |
|---|---|
| 規則識別碼 | CA1844 |
| 職稱 | 在子類別化 『Stream』 時,提供異步方法的記憶體型覆寫 |
| 類別 | 效能 |
| 修正程式是中斷或非中斷 | 不中斷 |
| 在 .NET 10 中預設啟用 | 建議 |
原因
衍生自 Stream 覆寫 ReadAsync(Byte[], Int32, Int32, CancellationToken) 但不會覆寫 ReadAsync(Memory<Byte>, CancellationToken)的類型。 或者,衍生自 Stream 覆寫 WriteAsync(Byte[], Int32, Int32, CancellationToken) 但不會覆寫 WriteAsync(ReadOnlyMemory<Byte>, CancellationToken)的類型。
檔案描述
已新增以記憶體為基礎的 ReadAsync 和 WriteAsync 方法來改善效能,這些方法會以多種方式完成:
- 它們分別傳回
ValueTask和 ,ValueTask<int>而不是Task和Task<int>。 - 它們允許傳入任何類型的緩衝區,而不需要對數位執行額外的複本。
為了實現這些效能優點,衍生自 Stream 的類型必須提供自己的記憶體型實作。 否則,預設實作會強制將記憶體複製到陣列,以呼叫數位型實作,進而降低效能。 當呼叫端傳入 Memory<T> 陣列不支援的 或 ReadOnlyMemory<T> 實例時,效能會受到更多影響。
如何修正違規
修正違規最簡單的方法是將數位型實作重寫為以記憶體為基礎的實作,然後在以記憶體為基礎的方法方面實作數位型方法。
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);
}
隱藏警告的時機
如果適用下列任何情況,則隱藏此規則的警告是安全的:
- 效能命中並不相關。
- 您知道您的
Stream子類別只會使用數位型方法。 - 您的
Stream子類別具有不支援記憶體型緩衝區的相依性。
隱藏警告
如果您只想要隱藏單一違規,請將預處理器指示詞新增至原始程式檔以停用,然後重新啟用規則。
#pragma warning disable CA1844
// The code that's violating the rule is on this line.
#pragma warning restore CA1844
[*.{cs,vb}]
dotnet_diagnostic.CA1844.severity = none
如需詳細資訊,請參閱 如何隱藏程式代碼分析警告。