C#5が非同期プログラミングのasync
およびawait
モデルを導入した後、C#コミュニティは、次のように、待機可能な型を返すメソッドに「非同期」サフィックスを追加する命名規則に到達しました。
interface Foo
{
Task BarAsync();
}
多くの静的コードアナライザー(Roslynベースと非Roslynベースの両方)は、非同期プログラミングに関するコードのにおいを検出するときに、この命名規則に依存するように作成されています。
C#8が非同期列挙型の概念を導入したため、それ自体は待機できませんが、await foreach
と組み合わせて使用できますが、IAsyncEnumerable
を返すメソッドの命名には2つのオプションがあるようです。
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#5の命名規則が明確に標準化され、プログラマーの意見に基づく判断に委ねられなかったなど、明確な命名規則のガイドライン(C#言語チーム、.NET Foundation、またはその他の機関による)はありましたか?
.NETチームがすでにが行うことよりも優れたガイドラインはありません。
IAsyncEnumerable<T>
_を返しますIAsyncEnumerable
として返されますIAsyncEnumerable
sに変換しますSystem.Linq.Async
_の他のすべての演算子は、その名前を保持します。 SelectAsync
やSelectAsAsyncEnumerable
はなく、Select
のみです。すべての場合において、メソッドの結果が何であるかは明らかです。すべての場合において、メソッドの結果は、使用する前に_await foreach
_で待機する必要があります。
したがって、realガイドラインは同じです-名前が動作を明確にすることを保証します:
AsAsyncEnumerable()
やToAsyncEnumerable()
など、名前がすでに明確な場合は、接尾辞を追加する必要はありません。Async
サフィックスを追加して、開発者が結果を_await foreach
_する必要があることを知らせます。コードアナライザーとジェネレーターは、メソッドの名前を実際には気にせず、コード自体を検査することで臭いを検出します。コードアナライザーは、メソッドや変数の呼び出し方法に関係なく、タスクまたは_await foreach
_ IAsyncEnumerable
を待つのを忘れたことを通知します。ジェネレーターは単純にリフレクションを使用してIAsyncEnumerable
をチェックし、_await foreach
_を発行できます
名前をチェックするのはstyleアナライザです。彼らの仕事は開発者がコードを理解できるようにコードが一貫したスタイルを使用することを保証することです。スタイルアナライザーは、メソッドが選択したスタイルに従っていないことを通知します。そのスタイルは、チームまたは一般的に受け入れられているスタイルガイドです。
そしてもちろん、プライベートインスタンスフィールドの一般的なプレフィックスが__
_であることは誰もが知っています。
これは非同期メソッドではないため、名前の末尾を「非同期」にすることはできません。そのメソッドのサフィックスは、メソッドが待機する必要があること、または結果がタスクとして処理されることを明確にするための規則です。
通常のコレクションを返す名前が適切だと思います。 GetFoos()など。
Async接尾辞とキーワードasync
も単なる定型文であり、下位互換性の引数以外には意味がありません。 C#は、yield
などの何かを追加する必要がないことを知っているので、IEnumerable
を返すメソッドでenumerable
を区別するのと同じように、これらの関数を区別するためのすべての情報を持っていますそのようなメソッドのキーワード。
C#がオーバーロードについて文句を言うからといって、Asyncサフィックスを追加する必要があります。したがって、基本的にこれら2つは同一であり、ポリモーフィズムのすべてのルールによって同じことを行います(ヒューマンファクターを採用していない場合)意図的に破損した動作の考慮)):
public interface IMyContract
{
Task<int> Add(int a, int b);
int Add(int a, int b);
}
しかし、コンパイラは文句を言うので、このように書くことはできません。しかし、ちょっと!それはこの1つの怪物を飲み込むでしょう:
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#量子コンピューターメソッド拡張(fantazy、huh)を追加した場合、おそらく別のサフィックスが必要になりますQuantなどのように、C#は他の方法で文句を言うからです。まったく同じ方法ですが、別の方法で機能します。ポリモーフィズムと同じように。インターフェイスと同じように。