簡體   English   中英

返回 IAsyncEnumerable 的方法是否有明確的命名約定?

[英]Is there a definitive naming convention for methods returning IAsyncEnumerable?

在 C# 5 為異步編程引入asyncawait模型后,C# 社區達成了命名約定,為返回可等待類型的方法添加“Async”后綴,如下所示:

interface Foo
{
   Task BarAsync();
}

許多靜態代碼分析器(基於 Roslyn 和非基於 Roslyn 的)已被編寫為在檢測異步編程的代碼異味時依賴此命名約定。

現在 C# 8 引入了異步可枚舉的概念,它們本身不是可await foreach ,但可以與await foreach結合使用,似乎有兩個選項可以用於命名返回IAsyncEnumerable方法:

interface Foo
{
    // No "Async" suffix, indicating that the return value is not awaitable.
    IAsyncEnumerable<T> Bar<T>();
}

或者

interface Foo
{
    // With "Async" suffix, indicating that the overall logic is asynchronous.
    IAsyncEnumerable<T> BarAsync<T>();
}

是否有關於上述選項的明確命名約定指南(來自 C# 語言團隊、.NET 基金會或其他權威機構),例如 C# 5 命名約定如何明確標准化而不是留給程序員基於意見的判斷?

沒有比 .NET 團隊已經做的更好的指導方針了:

  • ChannelReader.ReadAllAsync返回一個IAsyncEnumerable<T>
  • 在 EF Core 3 中,結果通過調用AsAsyncEnumerable()作為IAsyncEnumerable返回
  • 在 System.Linq.Async 中, ToAsyncEnumerable()將 IEnumerables、Tasks 和 Observables 轉換為IAsyncEnumerable
  • System.Linq.Async所有其他運算符都保留其名稱。 沒有SelectAsyncSelectAsAsyncEnumerable ,只有Select

在所有情況下,很清楚該方法的結果是什么。 在所有情況下,方法的結果都需要使用await foreach才能使用。

所以真正的指導方針保持不變 -確保名稱使行為清晰

  • 如果名稱已經明確,例如使用AsAsyncEnumerable()ToAsyncEnumerable() ,則無需添加任何后綴。
  • 在其他情況下,添加Async后綴,以便開發人員知道他們需要await foreach結果。

代碼分析器和生成器並不真正關心方法的名稱,它們通過檢查代碼本身來檢測氣味。 代碼分析器會告訴您,無論您如何調用方法和變量,您都忘記了等待任務或await foreach IAsyncEnumerable 生成器可以簡單地使用反射來檢查IAsyncEnumerable並發出await foreach

它是檢查名稱的樣式分析器。 他們的工作是確保代碼使用一致的風格,以便開發人員能夠理解代碼。 樣式分析器會告訴您某個方法不遵循您選擇的樣式。 這種風格可能是團隊的或普遍接受的風格指南。

當然,每個人都知道私有實例字段的通用前綴是_ :)

它不是異步方法,因此名稱不應以“Async”結尾。 該方法后綴是一個約定,它明確表示應該等待該方法,或者將結果作為任務處理。

我認為正常的集合返回名稱是合適的。 GetFoos() 或類似的。

異步后綴甚至關鍵字async只是樣板,它比一些向后兼容性爭論毫無意義等。 C# 具有區分這些函數的所有信息,就像它區分返回IEnumerable方法中的yield一樣,正如您所知,您不需要在此類方法上添加類似enumerable或其他一些關鍵字的任何內容。

您需要添加Async后綴只是因為 C# 會抱怨重載,所以本質上這兩個是相同的,並且它們按照多態性的所有規則做同樣的事情(如果我們不考慮故意破壞行為的人為因素):

public interface IMyContract
{
    Task<int> Add(int a, int b);
    int Add(int a, int b);
}

但是你不能這樣寫,因為編譯器會抱怨。 但是,嘿! 它會吞噬這個怪物:

public interface IMyContract : IEnumerable<int>, IEnumerable<long>
{
}

甚至這個:

public interface IMyContractAsync
{
    Task<int> Add(int a, int b);
}

public interface IMyContract : IMyContractAsync
{
    int Add(int a, int b);
}

所以就是這樣。 您添加Async只是為了阻止編譯器抱怨。 不是為了澄清事情。 不是為了讓他們變得更好。 如果沒有抱怨 - 沒有理由添加它,所以在你的情況下我會避免這種情況,除非它變成Task<IAsyncEnumerable>

PS:只是為了更好地理解這里的整個圖片 - 如果將來某個時候有人添加 C# 量子計算機方法擴展(幻想,呵呵),它將在不同的范式中運行,我們可能需要另一個后綴,如Quant或其他東西,因為 C#否則會抱怨。 這將是完全相同的方法,但它會以另一種方式工作。 就像多態一樣。 就像接口一樣。

根據 .Net 團隊,答案似乎是返回 IAsyncEnumerable<> 的方法應該以“Async”結尾。

.Net 運行時超級明星之一的 Stephen Toub 在此 GitHub 問題上針對 C# 流的公共 API 如此表示: https : //github.com/dotnet/runtime/issues/27547#issuecomment-478384285

是的[方法名稱將以“Async”結尾]。 最常見的消費將是通過 await foreach,它作為涉及異步的類似視覺指示器,允許與同步枚舉等進行區分。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM