OITA: Oika's Information Technological Activities

@oika 情報技術的活動日誌。

FxCop:List<T>を公開してはいけないという話

前回クラス間インタフェースの話をしていたのでついでに。

.NETにはFxCopというコード解析ツールがあって、コードの改善ポイントを指摘してくれる。
これが指摘するルールの中に「CA1002: Do not expose generic lists」というのがあって、
Listは継承できないから公開するメンバに使うなと言ってくる。
代わりとして、System.Collections.ObjectModel.Collectionを使えというんだけど、
これがあんまり好きでないのでどうしようという話。

何が嫌かというと、下のような書き方ができてしまう点。

            var array = new int[0];
            var collection = new Collection<int>(array);

            collection.Add(1);

これはコンパイルは通るけれども、Add()実行時にエラーになる。
コレクションの実体が配列なので、NotSupportedExceptionになるのだ。
こういうクラスに対してコーディングするのはちょっとこわい。

じゃあ代わりにどうするかというと、例えばListじゃなくてIListを使えば?
と思うわけだけど、残念ながらこれも同様に以下が実行時エラーになってしまう。

            IList<int> iList = new int[0];
            iList.Add(1);

なんと配列はIListを実装しているくせにAddができない。なんてこった。
インタフェースに対するコーディングもなにもあったもんじゃない。

そんなわけで結論としては、読み取り専用かもしれない状態で
CollectionやIListを渡されるよりは
素直にListで渡されたほうが、拡張性が犠牲になるにしても
まだ安心なんじゃないかという気がする。

あるいはもうIListとして受け渡すときは配列は渡さない、
配列を渡す可能性がある場合はIEnumerableにするという
コーディングルールを決めてやるとかでもいいのかもしれないですが。
一般的にどうしているものなんでしょう…。