型 'System.Collections.Generic.List<派生>' を 'System.Collections.Generic.List<基底>' に暗黙的に変換できません

基底クラスと派生クラスがあるとき、基底クラスのオブジェクトbへ派生クラスのオブジェクトdを代入することはできる。つまり「b=d;」はOKなのだが、しかしListを代入しようとするとエラーが起きるわけです。



つまり、「List<基底> bList」と「List<派生> dList」の2つのリストがあるとき、「bList = dList」はビルドエラーになる。

これ、できないのか、初めて知ったような気がする。

マイクロソフトのジェネリックの説明を読んでみると、それらしいことがさらっと書いてあった。ジェネリック クラス (C# プログラミング ガイド)の末尾あたり。
ジェネリック クラスは変化しません。 言い換えると、入力パラメーターが List<BaseClass> を指定するとき、List<DerivedClass> を指定するとコンパイル時エラーが表示されます。
 これはメソッドのパラメータに渡す場合の説明だけど、代入も同じようにエラーになるということか、、、知らなかった。

調べていくと、ジェネリックの共変性と反変性 という話につながるらしいが、よくわからない。Listは中身を変更できるから、「ListB = ListD」 したあとに、「ListD = (ListD) ListB」 できる保証がないからダメということなのだろうか。

とりあえずの解決策

リストをキャストすればエラーは出なくなる。
            var BList = DList.ToList<mm基底>();      
ちょっと無理やり感がありますな。

あと、IEnumerable はリストの中身を参照するだけなので(列挙子)、これを使えば代入可能になるみたい。AsEnumerable メソッドはこう云う感じで使えるのか。
            IEnumerable<mm基底> BIEnum;
            IEnumerable<mm派生> DIEnum = DList.AsEnumerable();
            BIEnum = DIEnum;
型をパラメータとして渡せるジェネリックはうまいアイデアなのだけど、継承が絡んでくるとややこしいところが現れて来て、なかなか難しいものだなあ。

コメント

このブログの人気の投稿

varchar をデータ型 numeric に変換中に、算術オーバーフロー エラーが発生しました。