123

不変クラスの作成に取り組んでいます。
すべてのプロパティを読み取り専用としてマークしました。

クラスのアイテムのリストがあります。
ただし、プロパティが読み取り専用の場合、リストは変更できます。

リストの IEnumerable を公開すると、不変になります。
クラスを不変にするために従わなければならない基本的なルールは何ですか?

4

8 に答える 8

129

私はあなたが正しい軌道に乗っていると思います-

  • クラスに注入されたすべての情報は、コンストラクターで提供する必要があります
  • すべてのプロパティはゲッターのみである必要があります
  • コレクション(または配列)がコンストラクターに渡される場合は、呼び出し元が後で変更しないように、コレクションをコピーする必要があります
  • コレクションを返す場合は、コピーまたは読み取り専用バージョンを返します(たとえば、ArrayList.ReadOnlyなどを使用します。これを前のポイントと組み合わせて、読み取り専用コピーを保存し、次の場合に返すことができます。呼び出し元がアクセスする)、列挙子を返す、またはコレクションへの読み取り専用アクセスを許可するその他のメソッド/プロパティを使用する
  • メンバーのいずれかが可変である場合でも、可変クラスのように見える可能性があることに注意してください。この場合、保持したい状態をコピーして、コピーしない限り、可変オブジェクト全体を返さないようにする必要があります。それらを呼び出し元に返す前に-別のオプションは、可変オブジェクトの不変の「セクション」のみを返すことです-この点を拡張するように私に勧めてくれた@BrianRasmussenに感謝します
于 2008-12-09T11:47:59.027 に答える
21

不変であるためには、すべてのプロパティとフィールドが読み取り専用である必要があります。また、リスト内のアイテム自体は不変である必要があります。

次のように、読み取り専用リストプロパティを作成できます。

public class MyClass
{
    public MyClass(..., IList<MyType> items)
    {
        ...
        _myReadOnlyList = new List<MyType>(items).AsReadOnly();
    }

    public IList<MyType> MyReadOnlyList
    {
        get { return _myReadOnlyList; }
    }
    private IList<MyType> _myReadOnlyList

}
于 2008-12-09T11:47:33.927 に答える
12

Also, keep in mind that:

public readonly object[] MyObjects;

is not immutable even if it's marked with readonly keyword. You can still change individual array references/values by index accessor.

于 2008-12-09T11:57:03.580 に答える
5

ReadOnlyCollectionクラスを使用します。System.Collections.ObjectModel名前空間にあります。

リストを返すもの (またはコンストラクター内) で、リストを読み取り専用コレクションとして設定します。

using System.Collections.ObjectModel;

...

public MyClass(..., List<ListItemType> theList, ...)
{
    ...
    this.myListItemCollection= theList.AsReadOnly();
    ...
}

public ReadOnlyCollection<ListItemType> ListItems
{
     get { return this.myListItemCollection; }
}
于 2008-12-09T13:18:33.367 に答える
2

もう 1 つのオプションは、内部コレクションをまったく公開する代わりに、ビジター パターンを使用することです。

于 2008-12-09T12:38:20.047 に答える