一人情シスのつぶやき

名古屋の中小企業で一人情シスをしている作者が、日々の業務で思うことをつぶやきます。

C#でのCollection系オブジェクトの受け渡し指針

C#でCollection系オブジェクト(IEnumerable, ICollection, IList等)の受け渡しをどうすべきか悩んでいた。 ListよりIList, EnumerableよりIEnumerableといった実装を含まないInterfaceが好ましいのは当然として、 あらゆるオブジェクトを想定してより抽象的なクラスを選択すべきというのは感覚的にわかるのだが、どうもしっくりこない。

以下の記事を見てなるほどと思った。 IEnumerable vs IReadOnlyList - Enterprise Craftsmanship

言語に依存しない一般的な方針としては、Postel’s law.として知られる(初めて知った...)

 be conservative in what you send, be liberal in what you accept, 

C#における具体的な方針として

prefer IEnumerable when accepting a collection; prefer IReadOnlyList when returning one.

確かに、引数は抽象的な方が使いやすいが、戻り値も抽象的だと結局toListしたりcastしたりしないといけないので使いにくいし、そもそもそんな使い方が正しいとは思えないので違和感があった。

IEnumerable - ICollection - IListという階層関係があるので、引数としてconservativeな(他の継承クラスも受け取れる)IEnumerableがよいというのはそのとおりだろう。 ただ、be liberal であるための解としてIReadOnlyListがあげられているが、これは利用側で内容を変更しないことがはっきりしている場合だろう。変更することが想定する場合はIListを返すべきと思われる。

複数のオブジェクトを格納する際には、IListの実装クラスがほとんどなので、これ以外を考慮する必要はとりあえずないと思われる。 DictionaryやHashtableを使う場合はIDictionaryあたりを返すのが妥当か?