3

outまたはrefパラメータを持つメソッドを持つ C# API を考えてみましょう。

Person FindPerson(string name, out int searchTime);

通常、out および ref パラメーターは設計上の臭いであるという事実に注意を払う必要はありません。たとえば、これがレガシー API であり、既存のメソッドの署名を変更できないとしましょう。ただし、非同期実行 (Windows Phone、WinRT アプリ) をサポートするために API を拡張する必要があります。コンパイルされない実装は次のとおりです。

Task<Person> FindPersonAsync(string name, out int searchTime)
{
    return Task.Factory.StartNew(() => this.FindPersonAsync(name, out searchTime));
}

この実装は、 outパラメータのためにコンパイルされません。そのため、API 署名を変更する必要があります。1 つの方法は、結果を task-of-person から task-of-tuple-of-person-and-int に変更することです。つまり、デリゲート実装は Person と int のタプルを返します。2 番目の方法は、カスタム構造を定義することです。

タプルの利点: タプルを使用すると、任意の API の非同期バージョンを簡単に定義するために使用できる非常に正式なアプローチが得られます。予測可能な実装 (新しい名前は定義されていません)。カスタム構造を使用するには、そのような場合ごとに新しい型とメンバーを発明する必要があります。

カスタム構造体の利点: タプルを使用するクライアント コードは、Item1およびItem2の名前を使用して Tuple 要素を参照する必要があります。これはあいまいです。

推奨事項が見つからず、当面はタプルを使用することにしました。しかし、ayns サポートを使用して API を拡張するときに、そのようなメソッドを処理するための推奨される方法があるかどうか疑問に思います。

4

1 に答える 1

1

この件に関するベスト プラクティスや推奨事項については知りません。しかし、私自身の経験からTupleすると、コードは見苦しく無意味なものItem1になります。

私は常にカスタムクラスを使用し、いくつかの規則を守っています。

  • Resultカスタム クラスの名前はlikeで終わりFindPersonResultます。
  • コンストラクターに特別なロジックを持たない POCO としてクラスを設計します。これにより、システムの他の部分や他の API (特にシリアライズとデシリアライズ) を操作しているときに予期せぬ事態が発生するのを防ぐことができます。
  • コレクションのフィールド/プロパティ (配列、リストなど) の初期値は、常に null 以外の空の値に設定してください。それも多くの場合に役立ちます。

これらは、私にとってシームレスに機能した問題に関する私の個人的な経験にすぎないことに注意してください.

于 2013-05-09T08:09:25.407 に答える