3

オブジェクトの個別のコレクションを選択し、それらをリストに追加してからリストを返すメソッドがあります。

最初、メソッドはIEnumerableを返しましたが、個別のコレクションを返すため、個別のオブジェクトをハッシュセットに追加して、代わりにISetを返すことができます。

ISetが返されたオブジェクトを変更可能にすることを感謝します(消費者はそれにAdd()を追加できます)が、とにかく新しいリストを返すので、これが私に影響を与えるとは思わないので、なぜ消費者がコレクションで何をするかを気にするのですか?彼らはそれを持っていますか?

問題は、これを行うべきかということです。または、IEnumerableを返すだけで、個別の要素のみが含まれていることを確認する必要があります(現在、テストによって保証されています)。

4

2 に答える 2

2

相変わらず、デザインでは、ここで矛盾する要件があります。優れたデザインの芸術は、作成する製品のこれらの要件の間で最適なバランスを選択することです。

インターフェイス設計の原則の1つは、インターフェイスを契約または約束と見なすことです。約束や契約が規範的でないほど、維持しやすくなることは明らかです。したがって、返品タイプとIEnumerable<T>は、一連のもののみを返品することを約束していることを意味します。「より厚い」またはより派生したタイプは、より規範的であり、維持するのがより困難な約束になります。

反射的に、戻り型がより派生していることを確認するために関数で作業を行っている場合、よりわかりにくい親型を返すことによってその作業を放棄するのは無駄に思えます。一連のものを定義するがすでにある場合はISet<T>、明示的にそれを返し、呼び出し元に個別のチェックの作業を保存します。

一般に、簡単な答えはありません。正しい答えは、発信者とシステムによって異なります。一般的なケースでは、発信者についての知識はありません。証拠がない場合、私たちは何も想定せず、弱い約束の具体的な利益を享受しなければなりません。したがって、一般的に、IEnumerable<T>これを使用すると、現在の既知のコストなしで、将来の柔軟性が向上します。

特定のケースでは、発信者がセットの返品の恩恵を受けることがわかっています。これは、シーケンスの明確さに関してバグが発生した場合です。明示してを返すことは理にかなっていますISet<T>。これは、個別のチェックの重複を防ぐのに役立ちます。警告を追加するために、これは、データがすべての可能な呼び出しに対して個別である場合にのみ意味があります。バグを提起した人だけでなく、すべての発信者に対して約束を守るようにする必要があります。

于 2012-11-27T09:52:41.653 に答える
0

あなたの問題を見る理由の1つは、メソッドが一意の要素のシーケンスを返す場合の「例による」です。戻り型はどうあるべきですか?

BCLには、そのようなメソッド(使用していると述べている)が含まれています。Enumerable.Distinct<T>

そのメソッドの戻り型はIEnumerableです。では、なぜ、実装が維持するすべての約束を自己投影しないタイプを使用するのでしょうか。私は2つの議論を見ることができます

  • メソッドの名前と意図から明らかです
  • IEnumerableコントラクトは、ISetと言うことを実現するのが簡単で、ほとんどの場合、コンシューマーが必要とするものを提供し、コンシューマーがISetを作成するのに十分でない場合に提供します。このため、コストは、値も取得された場合にのみ必要になります。

インターフェイスIDistinctEnumerableはそれを変更しますか?インターフェイスが提供する唯一の情報は名前にあります。型システムは、実行時のシーケンス内の要素が一意であることを保証できますが、名前に含まれているため、Distinctで使用したのと本質的に同じ引数です。外部から見たときに、メソッドがセットを返すことが期待される場合、これは永遠に続く可能性が高く、セットを返す価値があるかもしれません。ただし、一連の一意の要素とセットには違いがあります。

于 2012-11-27T11:13:45.170 に答える