CA1835:偏好在資料流程型類別中以記憶體為基礎的 ReadAsync/WriteAsync 方法多載
屬性 | 值 |
---|---|
類型名稱 | PreferStreamAsyncMemoryOverloads |
規則識別碼 | CA1835 |
標題 | 偏好以記憶體為基礎的多載在資料流程型類別中 ReadAsync/WriteAsync 方法 |
類別 | 效能 |
修正程式是中斷或非中斷 | 不中斷 |
預設在 .NET 8 中啟用 | 建議 |
原因
此規則會找出 和 WriteAsync
的位元組陣列型方法多載 ReadAsync
的等候調用,並建議改用以記憶體為基礎的方法多載,因為它們更有效率。
檔案描述
記憶體型方法多載的記憶體使用量比位元組陣列型多載更有效率。
規則適用于 ReadAsync
繼承自 Stream 的任何類別和 WriteAsync
叫用。
只有在 方法前面加上 await
關鍵字時,規則才有效。
偵測到的方法 | 建議的方法 |
---|---|
ReadAsync(Byte[], Int32, Int32, CancellationToken) | ReadAsync(Memory<Byte>, CancellationToken) |
ReadAsync(Byte[], Int32, Int32) | ReadAsync(Memory<Byte>, CancellationToken)在 CancellationToken C# 或 Nothing Visual Basic 中設定為 default 。 |
WriteAsync(Byte[], Int32, Int32, CancellationToken) | WriteAsync(ReadOnlyMemory<Byte>, CancellationToken) |
WriteAsync(Byte[], Int32, Int32) | WriteAsync(ReadOnlyMemory<Byte>, CancellationToken)在 CancellationToken C# 或 Nothing Visual Basic 中設定為 default 。 |
重要
請務必將 offset
和 count
整數引數傳遞至已建立 Memory
的 或 ReadOnlyMemory
實例。
注意
規則 CA1835 適用于所有 .NET 版本,其中記憶體型多載可供使用:
- .NET Standard 2.1 和更新版本。
- .NET Core 2.1 和更新版本。
如何修正違規
您可以手動修正它們,也可以選擇讓 Visual Studio 為您執行,方法是將滑鼠停留在方法調用旁邊顯示的燈泡上,然後選取建議的變更。 範例:
此規則可以偵測 和 WriteAsync
方法的各種違規 ReadAsync
。 以下是規則可以偵測到的案例範例:
範例 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);
}
}
}
傳回值是由 wrapping 方法傳回,而不是等候:
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
如需詳細資訊,請參閱 如何隱藏程式碼分析警告 。