Catatan
Akses ke halaman ini memerlukan otorisasi. Anda dapat mencoba masuk atau mengubah direktori.
Akses ke halaman ini memerlukan otorisasi. Anda dapat mencoba mengubah direktori.
| Properti | Nilai |
|---|---|
| ID Aturan | CA1844 |
| Judul | Memberikan penggantian berbasis memori untuk metode asinkron ketika membuat subkelas dari 'Stream' |
| Kategori | Performa |
| Perbaikan bersifat merusak atau tidak merusak | Tidak terputus |
| Diaktifkan secara default di .NET 10 | Sebagai saran |
| Bahasa yang berlaku | C# dan Visual Basic |
Penyebab
Jenis yang berasal dari Stream menggantikan ReadAsync(Byte[], Int32, Int32, CancellationToken) tetapi tidak menggantikan ReadAsync(Memory<Byte>, CancellationToken). Atau, jenis yang berasal dari Stream menggantikan WriteAsync(Byte[], Int32, Int32, CancellationToken) tetapi tidak menggantikan WriteAsync(ReadOnlyMemory<Byte>, CancellationToken).
Deskripsi aturan
Metode ReadAsync dan WriteAsync berbasis memori ditambahkan untuk meningkatkan performa, yang dicapai dengan berbagai cara:
- Mereka mengembalikan
ValueTaskdanValueTask<int>alih-alihTaskdanTask<int>, masing-masing. - Mereka memungkinkan semua jenis buffer untuk diteruskan tanpa harus melakukan salinan tambahan ke array.
Untuk mewujudkan manfaat performa ini, jenis yang berasal dari Stream harus memberikan implementasi berbasis memori mereka sendiri. Jika tidak, implementasi default akan dipaksa untuk menyalin memori ke dalam array untuk memanggil implementasi berbasis array, yang mengakibatkan penurunan performa. Saat penelepon melewati instans Memory<T> atau ReadOnlyMemory<T> yang tidak didukung oleh array, performa akan terpengaruh lebih banyak.
Cara memperbaiki pelanggaran
Cara term mudah untuk memperbaiki pelanggaran adalah dengan menulis ulang implementasi berbasis array Anda sebagai implementasi berbasis memori, lalu menerapkan metode berbasis array dalam hal metode berbasis memori.
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);
}
Kapan harus menekan peringatan
Aman untuk menekan peringatan dari aturan ini jika salah satu situasi berikut berlaku:
- Penurunan performa bukan suatu kekhawatiran.
- Anda tahu bahwa subkelas Anda
Streamhanya akan pernah menggunakan metode berbasis array. - Subkelas Anda
Streammemiliki dependensi yang tidak mendukung buffer berbasis memori.
Menyembunyikan peringatan
Jika Anda hanya ingin menyembunyikan satu pelanggaran, tambahkan arahan praprosedur ke file sumber Anda untuk dinonaktifkan lalu aktifkan kembali aturannya.
#pragma warning disable CA1844
// The code that's violating the rule is on this line.
#pragma warning restore CA1844
Untuk menonaktifkan aturan untuk file, folder, atau proyek, atur tingkat keparahannya ke none dalam file konfigurasi.
[*.{cs,vb}]
dotnet_diagnostic.CA1844.severity = none
Untuk informasi selengkapnya, lihat Cara menyembunyikan peringatan analisis kode.