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

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

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


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

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

            collection.Add(1);

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

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

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

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

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

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