CA1835: ストリームベースのクラスで ReadAsync/WriteAsync メソッドのメモリベースのオーバーロードを優先する
プロパティ | 値 |
---|---|
型名 | PreferStreamAsyncMemoryOverloads |
ルール ID | CA1835 |
Title | ストリームベースのクラスで ReadAsync/WriteAsync メソッドのメモリベースのオーバーロードを優先する |
[カテゴリ] | パフォーマンス |
修正が中断ありか中断なしか | なし |
.NET 9 では既定で有効 | 提案として |
原因
この規則は、ReadAsync
および WriteAsync
のバイト配列ベースのメソッドのオーバーロードの待機中の呼び出しを特定し、より効率的であるという理由から、代わりにメモリベースのメソッドのオーバーロードを使用することを提案します。
規則の説明
メモリベースのメソッドのオーバーロードは、バイト配列ベースのものよりもメモリ使用の効率性に優れています。
この規則は、Stream から継承するすべてのクラスの ReadAsync
および WriteAsync
呼び出しで機能します。
この規則は、メソッドの前に await
キーワードが付いている場合にのみ機能します。
検出されたメソッド | 提案されたメソッド |
---|---|
ReadAsync(Byte[], Int32, Int32, CancellationToken) | ReadAsync(Memory<Byte>, CancellationToken) |
ReadAsync(Byte[], Int32, Int32) | ReadAsync(Memory<Byte>, CancellationToken)。CancellationToken は、C# では default に、Visual Basic では Nothing に設定します。 |
WriteAsync(Byte[], Int32, Int32, CancellationToken) | WriteAsync(ReadOnlyMemory<Byte>, CancellationToken) |
WriteAsync(Byte[], Int32, Int32) | WriteAsync(ReadOnlyMemory<Byte>, CancellationToken)。CancellationToken は、C# では default に、Visual Basic では Nothing に設定します。 |
重要
offset
および count
の整数の引数を、作成された Memory
または ReadOnlyMemory
のインスタンスに渡すようにしてください。
注意
規則 CA1835 は、メモリベースのオーバーロードが使用可能なすべての .NET バージョンで使用できます。
- .NET Standard 2.1 以降。
- .NET Core 2.1 以降。
違反の修正方法
これらは手動で修正することも、メソッドの呼び出しの横に表示される電球にマウス カーソルを置いて、提案された変更を選択することによって、Visual Studio に実行を任せることを選ぶこともできます。 例:
この規則によって、ReadAsync
と WriteAsync
メソッドのさまざまな違反を検出できます。 規則が検出できるケースの例を次に示します。
例 1
CancellationToken
引数を指定しないときと指定したときの ReadAsync
の呼び出し:
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);
}
}
}
解決策:
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);
}
}
}
例 2
CancellationToken
引数を指定しないときと指定したときの WriteAsync
の呼び出し:
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);
}
}
}
解決策:
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);
}
}
}
例 3
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);
}
}
}
解決策:
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);
}
}
}
非違反
次に、規則が実行されない呼び出しの例をいくつか示します。
戻り値は、待機するのではなく、Task
変数に保存されます。
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);
}
}
}
戻り値は、待機するのではなく、折り返しメソッドによって返されます。
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);
}
}
戻り値は、待機中のメソッド ContinueWith
を呼び出すために使用されます。
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 => { /* ... */ });
}
}
}
どのようなときに警告を抑制するか
ストリームベースのクラスでバッファーの読み取りまたは書き込み時のパフォーマンスの向上に関心がない場合は、この規則の違反を抑制することをお勧めします。
警告を抑制する
単一の違反を抑制するだけの場合は、ソース ファイルにプリプロセッサ ディレクティブを追加して無効にしてから、規則をもう一度有効にします。
#pragma warning disable CA1835
// The code that's violating the rule is on this line.
#pragma warning restore CA1835
ファイル、フォルダー、またはプロジェクトの規則を無効にするには、構成ファイルでその重要度を none
に設定します。
[*.{cs,vb}]
dotnet_diagnostic.CA1835.severity = none
詳細については、「コード分析の警告を抑制する方法」を参照してください。
関連項目
.NET