http://tack41tu.hatenablog.com/entry/2019/02/28/092329

で記載した方針を受けて、最近はCollectionに関してはIEnumerableで受けて、IReadOnlyListで返す基本方針としている。 一方で、プロパティの変更による予期せぬ誤動作を防ぐために、POCOについてはコンストラクタで初期とを設定し、setterを提供しないことでImmutableな形としている。

ただ、そうなるとCollectionもコンストラクタで渡す必要があるが、アルゴリズムの関係などでCollectionのメンバーは後で追加したいことがある。例えばDBからデータを取得して、鑑データの属性として明細データのCollectionを持たせる場合に、鑑データのclassをいったん生成した後、明細データを都度追加したいことが多い。要は短期間だけメンバーを追加したい。

POCOに渡すCollectionの参照を呼び出し側で保持し、鑑データのコンストラクタに渡した後で呼び出し側で持っているCollectionの参照をもとにメンバーを追加したのだが、なぜか反映されない。

結論としては、POCO内ではCollectionをListとして保持しており、コンストラクタでIEnumerableで受けた際に直ちにtoListで変換していた。これだとその時点でオブジェクトがコピーされてしまい、呼び出し側で持っている参照とは別物になってしまう。 そこで、IEnumerableで受けたオブジェクトは内部的にもIEnumerableで保持し、getterで参照された際にtoListしてIReadOnlyList型として返すことで解決した。こうすれば呼び出し側で持っている参照とPOCOで持っているクラスは全く同じとなり、呼び出し側でメンバーを追加、削除すればPOCOにも反映される。getterで参照する場合はそもそもIReadOnlyList型としてわたるのでメンバーの編集はできない。castすればできなくもないかもしれないが、少なくともそれは保証対象外という意図を明示できる。