3

次の例を検討してください。

サードパーティが使用するライブラリを開発したとします。ライブラリには を受け入れるメソッドがありますIEnumerable。これは、渡されたコレクションの実装から抽象化されるため、優れています。ただし、入力パラメーターを取得すると、遅延評価が発生します。

public interface IStorage<in T>
{
  void Store(IEnumerable<T> values);
}

public class FileStorage<T> : IStorage<T>
{
  public void Store(IEnumerable<T> values)
  {
    foreach (var value in values) { /*Evaluation of IEnumerable*/}
  }
}

一部のクライアントは、私のライブラリを次のように使用しています。

  IEnumerable<int> values;
  try
  {
    values = new[] { "1", "2", "three" }.Select(int.Parse);
  }
  catch (Exception)
  {
    values = Enumerable.Empty<int>();
  }

  var storage = new FileStorage<int>();
  storage.Store(values);

Storeこれにより、評価が行われるメソッド内で例外が発生します。Store取るメソッドを設計した場合List<T>、それが安全に列挙可能な Ts のコレクションであると確信できます。問題は、API を設計するときに避けるべきIEnumerableか、例外を発生させる可能性があるため、必要に応じて安全なコンテキストで API を許可して列挙する必要があるかどうかです。

4

5 に答える 5

3

Krzysztoc Cwalina と Brad AdamsによるFramework Design Guidelinesブックによると。

http://blogs.msdn.com/b/kcwalina/archive/2008/01/03/frameworkdesignguidelines2ndedition.aspx

それはあなたがすることをお勧めします...

252ページからの抜粋(8.3.1)

コレクション パラメータ

パラメータ型として可能な限り特殊化されていない型を使用してください。コレクションをパラメーターとして受け取るほとんどのメンバーは、IEnumerable インターフェイスを使用します。

 public void PrintNames(IEnumerable<string> names) {
      foreach(string name in names) {
          Console.WriteLine(name);
      } }

Count プロパティにアクセスするためだけに、ICollection または ICollection をパラメータとして使用しないでください。

代わりに、IEnumerable または IEnumerable を検討し、オブジェクトが ICollection または ICollection を実装しているかどうかを動的にチェックします。

ところで、それは素晴らしい本であり、読む価値があり、現在本当に楽しんでいます。PS これを書いた人たちは、.NET フレームワークの作成を手伝ってくれました

于 2012-07-19T19:15:42.010 に答える
1

個人的には、メソッド内から例外が発生するという問題は見られません。
これエラーであり、APIのユーザーはそれについて知っている必要があります。

于 2012-07-19T18:51:20.503 に答える
1

クライアントのコードにバグがあるという事実は、あなたの問題ではありません。プログラムを動かしたいのなら、バグのあるコードを書くのをやめるように言いましょう。これらのクエリが遅延評価され、彼らがこれを明らかに知らないという事実から彼らを保護することはできません。

コレクションを列挙したときに何が起こるかを処理するのはクライアントの責任です。クライアントが遅延評価されたコレクションを渡した場合、この遅延評価がスローされないようにするのはクライアントの責任です (定義したパラメーターの場合)。 . この不変条件を破ることが彼らの問題です。

于 2012-07-19T18:54:26.100 に答える
0

はい、ライブラリのパラメーターとして最も抽象的なインターフェイスを使用することをお勧めします。そのようにして、それらの項目に対する契約を定義します。

コレクションを列挙するだけでよい場合は、IEnumerable が最適です。

アイテムの追加、インデックス作成などを可能にしたい場合は、IList が正しい選択です。

于 2012-07-19T18:53:19.930 に答える
0

補足として、ここでの問題は、API が IEnumerable を取得することではありません。実際の問題は .Select 呼び出しにあります。遅延評価は、IEnumerable インターフェイスの機能ではなく、LINQ の機能です。

そうです、IEnumerable をパラメーターとして使用する必要があります。リソースの読み込みと管理は、あなたではなく、完全にクライアントの管理下にあります。クライアントが IEnumerable の実装を潜在的に渡す可能性があり、例外の報告が遅れる可能性があるからといって、API の保守性と柔軟性を犠牲にする十分な理由にはなりません。

于 2012-07-19T18:59:31.420 に答える