2008年10月27日
川俣晶の縁側ソフトウェア技術雑記total 20038 count

C#のジェネリックは基底クラスを型引数に指定した対象に変換できない

Written By: 川俣 晶連絡先

 タイトルの「C#のジェネリックは基底クラスを型引数に指定した対象に変換できない」とは意味が良く分かりませんが。罠っぽい問題に遭遇したのでメモっておきます。

サンプルソース §

using System;

using System.Collections.Generic;

using System.Linq;

using System.Text;

class A {}

class B : A {}

class Program

{

    private static void method1(A[] array) { }

    private static void method2(List<A> list) { }

    static void Main(string[] args)

    {

        method1(new B[] { }); // ケース1

        method2(new List<B>()); // ケース2

        method1((new B[] { }).ToArray()); // ケース3

    }

}

コンパイル結果 §

エラー 1 'Program.method2(System.Collections.Generic.List<A>)' に最も適しているオーバーロード メソッドには無効な引数がいくつか含まれています。 d:\w\test\ConsoleApplication65\ConsoleApplication65\Program.cs 16 9 ConsoleApplication65

エラー 2 引数 '1': 'System.Collections.Generic.List<B>' から 'System.Collections.Generic.List<A>' に変換できません。 d:\w\test\ConsoleApplication65\ConsoleApplication65\Program.cs 16 17 ConsoleApplication65

解説 §

 ケース1とケース3は通りますが、ケース2は通りません。

 つまり、基底クラスを型として持つ配列への変換は自動的に実行できますが、List<T>への変換はできません。C#プログラミングではA[]とList<A>は似たような存在として使い、本当はA[]が欲しい場合でもList<A>として作成してからToArrayすることも多いと思いますが、このようなケースではList<A>のままでは引数に渡せないことになります。しかし、ToArrayしてしまうと、もはやアイテムの追加はできなくなります。

追記 §

 ではこのようなケースにはどのように対処すべきか、というと、たぶんジェネリックメソッドにして型制約を付けるのが正解ではないかと思いました。以下のような感じです。

 この場合、引数listに格納された要素はAまたはAを継承した値であることが制約されるので、method2内からは"list[0].hoge"のような感じでAに含まれるhogeをキャスト無しで呼び出せます。

using System;

using System.Collections.Generic;

using System.Linq;

using System.Text;

class A { }

class B : A {}

class Program

{

    private static void method1(A[] array) { }

    private static void method2<T>(List<T> list) where T : A { }

    static void Main(string[] args)

    {

        method1(new B[] { });

        method2<B>(new List<B>());

        method1((new B[] { }).ToArray());

    }

}

追記の感想 §

 型制約は滅多に使わないので、思い出すのに時間が掛かってしまいました。

Facebook

このコンテンツを書いた川俣 晶へメッセージを送る

[メッセージ送信フォームを利用する]

メッセージ送信フォームを利用することで、川俣 晶に対してメッセージを送ることができます。

この機能は、100%確実に川俣 晶へメッセージを伝達するものではなく、また、確実に川俣 晶よりの返事を得られるものではないことにご注意ください。

このコンテンツへトラックバックするためのURL

https://mag.autumn.org/tb.aspx/20081027145421
サイトの表紙【技術雑記】の表紙【技術雑記】のコンテンツ全リスト 【技術雑記】の入手全リスト 【技術雑記】のRSS1.0形式の情報このサイトの全キーワードリスト 印刷用ページ

管理者: 川俣 晶連絡先

Powered by MagSite2 Version 0.36 (Alpha-Test) Copyright (c) 2004-2021 Pie Dey.Co.,Ltd.