Note
L’accès à cette page nécessite une autorisation. Vous pouvez essayer de vous connecter ou de changer d’annuaire.
L’accès à cette page nécessite une autorisation. Vous pouvez essayer de changer d’annuaire.
| Propriété | Value |
|---|---|
| Identificateur de la règle | CA1844 |
| Titre | Fournir des remplacements basés sur la mémoire des méthodes async lors du sous-classement de 'Stream' |
| Catégorie | Performances |
| Le correctif est cassant ou non cassant | Sans rupture |
| Activé par défaut dans .NET 10 | À titre de suggestion |
Cause
Un type dérivé de Stream remplace ReadAsync(Byte[], Int32, Int32, CancellationToken), mais ne remplace pas ReadAsync(Memory<Byte>, CancellationToken). De même, un type dérivé de Stream remplace WriteAsync(Byte[], Int32, Int32, CancellationToken), mais ne remplace pas WriteAsync(ReadOnlyMemory<Byte>, CancellationToken).
Description de la règle
Les méthodes ReadAsync et WriteAsync basées sur la mémoire ont été ajoutées pour améliorer les performances, ce qu’elles effectuent de plusieurs façons :
- Elles retournent respectivement
ValueTasketValueTask<int>au lieu deTasketTask<int>. - Elles permettent de passer n’importe quel type de mémoire tampon sans avoir à effectuer une copie supplémentaire dans un tableau.
Ces avantages en matière de performances sont possibles si les types qui dérivent de Stream fournissent leur propre implémentation basée sur la mémoire. Dans le cas contraire, l’implémentation par défaut est forcée de copier la mémoire dans un tableau pour pouvoir appeler l’implémentation de type tableau, ce qui réduit les performances. Lorsque l’appelant transmet une instance de Memory<T> ou de ReadOnlyMemory<T> qui ne s’appuie pas sur un tableau, l’effet sur les performances est accru.
Comment corriger les violations
Le moyen le plus simple de corriger les violations consiste à réécrire l’implémentation de type tableau comme une implémentation basée sur la mémoire, puis à implémenter les méthodes de type tableau sous forme de méthodes basées sur la mémoire.
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);
}
Quand supprimer les avertissements
Vous pouvez sans risque supprimer un avertissement de cette règle dans chacune des situations suivantes :
- L’impact sur les performances ne constitue pas un problème.
- Vous savez que votre sous-classe
Streamn’utilisera jamais que des méthodes de type tableau. - Votre sous-classe
Streampossède des dépendances qui ne prennent pas en charge les mémoires tampons basées sur la mémoire.
Supprimer un avertissement
Si vous voulez supprimer une seule violation, ajoutez des directives de préprocesseur à votre fichier source pour désactiver et réactiver la règle.
#pragma warning disable CA1844
// The code that's violating the rule is on this line.
#pragma warning restore CA1844
Pour désactiver la règle sur un fichier, un dossier ou un projet, définissez sa gravité sur none dans le fichier de configuration.
[*.{cs,vb}]
dotnet_diagnostic.CA1844.severity = none
Pour plus d’informations, consultez Comment supprimer les avertissements de l’analyse de code.