3

私は現在 C# を学んでおり、ISet を含むクラスがある状況にあります。私はクライアントがこのセットを直接変更することを望んでおらず、ほとんどのクライアントは追加と削除のみを行っており、これを行うためにクラスを通じてアクセサーを提供しています。

しかし、このセットとその内容についてもっと知りたいというクライアントが 1 人います。この 1 つのクライアントの多くのメソッドでラッパー クラス自体を混乱させたくないので、セット自体を不変の方法で返すことができるようにしたいと考えています。

私はできないことがわかりました-まあ、そうではありません。私が持っていると思われる唯一のオプションは次のとおりです。

  1. IEnumerable を返します (いいえ: 機能が制限されています)。
  2. ReadOnlyCollection (いいえ: リストです);
  3. コピーを返します (いいえ: 悪い形式の私見です。クライアントは、実際のオブジェクトを変更しないことに気付かずに、返されたコレクションを変更できます。さらに、パフォーマンスのオーバーヘッドがあります)。
  4. 独自の ReadOnlySet を実装します (いいえ: ISet から派生させる必要があるため、ミューテーターを実装する必要があります。おそらく例外を発生させます。実行時ではなく、時間エラーをコンパイルします)。

何か不足していますか?私は不合理ですか?ラッパーでアクセサの完全なセットを提供する唯一のオプションですか? 大多数のクライアントに対してラッパーをクリーンに保つという当初の意図は間違っていますか?

2つの質問:

  1. 標準の C# 不変コレクション インターフェイスがないのはなぜですか? それはかなり合理的な要件のように思えますか?

  2. ReadOnlyCollection が実際には ReadOnlyList であるのに、ReadOnlyCollection と呼ばれるのが煩わしいのはなぜですか? 私はそれがリストであることがわかるまで、弾丸を噛んでそれを使用するつもりでした(そして私はセットを使用します)。

4

4 に答える 4

8

標準の C# 不変インターフェイスがないのはなぜですか? それはかなり合理的な要件のように思えますか?

  • 標準の C# immutable¹ インターフェイスは既に存在します。それが呼び出されIEnumerable、すべてのコンテナーがそれを実装します。

  • 多くの種類の不変性があるため、より強力な不変インターフェースには問題があります。BCL チームが不変性の 1 つの定義を選択し、それを不変性ステータスに昇格させることにし場合、将来、別の種類の不変性を探している人々がその選択について不満を言うことは確実です。

    すべての人を満足させるには、すべての不変性の混乱を整理するだけでなく、多くのインターフェイスを作成し (運が良ければ、それらにも適切な名前が付けられます)、これらすべての不変性の概念を十分に言語に焼き付けて、不変性を第一級の市民にすることを意味します -- 覚えておいてくださいパブリッククラスを出荷すると、そのパブリックインターフェイスは永遠に不変です(しゃれが意図されています)。これらすべてがあればよいのですが、費用対効果の比率については本当に懐疑的です。

  • を定義することは難しくありIReadOnlyListませIReadOnlySetん。必要な場合などです。繰り返しますが、マイナス 100 ポイントであるため、それらはまだ存在していないと思います。

  • ReadOnlyCollection私見は、譲歩またはBCLの内部で必要とされ、世界に公開されたクラスのいずれかです。なぜなら、BCLチームにとって本当に低コストで無料の機能だからです(とにかく実装、文書化、テストする必要があるため)。いずれにせよ、たまたま華やかな界隈に住んでいるとは思えません。System.Collections.Generic

ReadOnlyCollection が実際には ReadOnlyList であるのに、ReadOnlyCollection と呼ばれるのが煩わしいのはなぜですか? 私はそれがリストであることがわかるまで、弾丸を噛んでそれを使用するつもりでした(そして私はセットを使用します)。

BCL チームは時間をさかのぼって修正できることを望んでいるに違いありません。これはほぼ確実に、同等の範囲のライブラリに不可避的に潜り込む小さな矛盾の 1 つだからです。ReadOnlyCollection実装されているのでIList、間違いなく呼び出されているはずReadOnlyListです。

ただし、「リスト」が「コレクション」よりも多くの機能を提供することを考えると、これがどのようにあなたを止めるのかわかりません。どちらも ではないSetので、いずれにせよそれらの上にセット関連の機能を構築する必要があります (これは良い考えではありません; の上に読み取り専用のセマンティクスを構築するだけですSet)。


¹ ここでは「不変」という言葉をよく使いますが、その言葉には特別な意味はありません。「読み取り専用」を使用する方が適切だと思いますが、一貫性を保つために、あなたが選んだ言葉を使用します。

于 2012-05-05T15:22:13.503 に答える
1

これは役立つかもしれません、 http://blogs.msdn.com/b/jaredpar/archive/2008/04/22/api-design-readonlycollection-t.aspx

于 2012-05-05T15:08:35.230 に答える
1

不変性と読み取り専用ラッパーの両方について .net でより適切なサポートがあればいいのですが、概念には大きな違いがあることに注意することが重要だと思います。読み取り専用ラッパーは、その作成者に対して、そのラッパーの消費者が基礎となるオブジェクトを変更できないことを約束しますが、基礎となるオブジェクト自体が変更されないことを消費者に約束しません。対照的に、不変オブジェクトは、その値が変更されないことをその作成者と消費者に約束します。

さまざまな種類の免疫があるという考えがなぜ問題になるのか、私にはよくわかりません。ImmutableList<T>修飾されていないジェネリックがある場合、作成時とT同じ が常に含まれることが期待Tされます。コレクションは、 のプロパティが変更される可能性があるかどうかにまったく影響を与えTません。

ドラザーがあれば、ほとんどのコレクション関連のインターフェイスには、読み取り可能、変更可能、および不変のバリアントが含まれます (変更可能と不変はどちらも読み取り可能から拡張されます)。また、書き込み専用の反変 IAppendable インターフェイスと、IImmutableEnumerable派生元IEnumerable(IEnumerable (および IImmutableEnumerable) にメソッドを追加します) も追加しToImmutableます。実装によって不変コレクションを構築できますが、場合によっては、それが最良のアプローチ. たとえば、可変オブジェクトIEnumerableは、可変要素の可変数のコピーを返すことによって実装する場合があります. コピー数が多い場合、単純なコレクションへの変換は非常に無駄になる可能性があります.

于 2012-06-16T05:53:38.350 に答える
1

データを同じまたは異なる構造の別のインスタンスに実際にコピーせずに、セットの読み取り専用の「コピー」を提供する唯一の方法は、ラッパーを使用してすべての項目追加および-例外をスローするメソッドを削除します。

セットがISetとにかくのみ公開されている場合、消費者は、ラッパーに含まれるものに関係なく、インターフェイスで定義されたメンバーのみを表示します-それは悪いことではないようです.

于 2012-05-05T14:58:58.947 に答える