DOBON.NETプログラミング道掲示板

■34411 / 1階層)  共変性と反変性ってこういうこと?
□投稿者/ 魔界の仮面弁士 大御所(1268回)-(2019/12/06(Fri) 11:05:31)
  • アイコン2019/12/06(Fri) 20:03:48 編集(投稿者)

    No34410に返信(VBはじめましたさんの記事)
    > (以下、自分なりの解釈)
    改行無い 苦行じゃない?
    その説明 C# 混じってない?


    > 例えば、List<String>型データとArray型のデータに対して同じ機能を実行いたい場合、
    ここの文面は、List(Of String) に直したほうが良いですね。


    > メソッドからの返り値の受け渡しでも発生し、返り値の場合は、
    間違っているわけではないのですが、Return Value については、
    一般的には「戻り値」と呼びます。Microsoft の資料でもそうなっているはず。


    > 次ような解釈で問題ないでしょうか?
    概要としては間違っていないと思います。


    ただし『配列』については、まだジェネリックが無かった当時の名残で、
    特例措置として共変性を持つように設計されている点に注意して下さい。
    本来は、配列に関して共変性を認めるべきではないのですが、
    互換性の都合で、ここの仕様は変更できなかったのですね。

    Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click
      Dim x() As List(Of Button) = Nothing
      'Dim y() As List(Of Control) = x 'これは NG(コンパイルエラー)

      Dim b() As Button = {Button1}
      Dim c() As Control = b '歴史的な事情から、配列は共変となっています


      'このような場合、書き込み(反変)は本来 NG ですが、コンパイルできてしまいます。
      'そのため、実行時に ArrayTypeMismatchException 例外となってしまいます。
      c(0) = Me '本来は List(Of ) 同様、コンパイル時に検出できるのが望ましい。
    End Sub



    > ジェネリックを勉強していると、共変性と反変性ってでてきます。

    これ自体はジェネリックに限定した用語では無いですね。

    『型の共変性』とは、広い型から狭い型へ変換が常に安全に行えること。(Covariance)
    『型の反変性』とは、狭い型から広い型へ変換が常に安全に行えること。(Contravariance)
    『型の双変性』とは、広い型にも狭い型にも変換できること。(Bivariance)
    『型の不変性』とは、型を変換できないこと。(Invariance)


    上記にある「広い型」や「狭い型」ですが、ジェネリックで使われる場合、
    たとえば Double と Integer などの関係性を示しているのではありません。

    ここでは継承・派生・インターフェイス実装などの関係性、たとえば
    「TextBox のインスタンスを Control 型の引数に代入しても問題無い」とか
    「Control 型の戻り値なプロパティから TextBox のインスタンスが取得されても問題無い」
    といった関係性を指しています。


    さて、VB2010 / C# 2010 からは、ジェネリックの型パラメーターに対して
    Out / out キーワードで共変性を、In / in キーワードで反変性を
    指定できるようになりました。
    『ジェネリックを勉強していると、共変性と反変性ってでてきます。』というのも
    それが要因でしょう。

    そのため、「ジェネリックにおける共変性と反変性」について学ぶのであれば、
    In/Out キーワードについても、合わせて学んでおくべきかと思います。

    ジェネリックの共変性と反変性について書かれた下記の記事でも、In や Out が出てきますね。
    https://www.atmarkit.co.jp/fdotnet/chushin/vb2010features_01/vb2010features_01_03.html



    提示頂いたサンプルにおいて、 IEnumerable(Of T) ジェネリック型インターフェイスが登場しています。
    この型についてヘルプで調べてみると、VB2008 (.NET Framework 3.5) までは
      Public Interface IEnumerable(Of T)
       Implements IEnumerable
    という定義であると書かれていたのに対し、VB2010 (.NET Framework 4) からは
      Public Interface IEnumerable(Of Out T)
       Implements IEnumerable
    であることが分かるはずです。Out が付与されたことで、共変性を明示することができます。

    一方、反変性の In については、Action(Of T) ジェネリック型デリゲートなどで使われています。
    VB2008 付属の .NET Framework 3.5 ヘルプでは
      Public Delegate Sub Action(Of T) (obj As T)
    という定義だったものが、.NET Framework 4 からは
      Public Delegate Sub Action(Of In T)(obj As T)
    という定義に変わっていますね。



    > サンプルとして適切かどうか?

    共変性と反変性の説明のためのサンプルとして書いたのであれば、
    どの部分が共変性で、
    どの部分が反変性を示しているのかを、
    コメントで説明した方が良いかと思います。


    また、Visual Basic のサンプルとしてなら、

    '『渡したデータ型は、System.Collections.Generic.List`1[System.Int32]』
    Console.WriteLine("渡したデータ型は、{0}", myList.GetType)
    '『渡したデータ型は、System.Int32[]』
    Console.WriteLine("渡したデータ型は、{0}", myArray.GetType)

    よりも

    '『渡したデータ型は、List(Of Integer)』
    Console.WriteLine("渡したデータ型は、{0}", TypeName(myList))
    '『渡したデータ型は、Integer()』
    Console.WriteLine("渡したデータ型は、{0}", TypeName(myArray))

    の方が分かりやすいと思います。


    それと、Function の宣言途中で改行する場合、
    「As IEnumerable(Of Integer)」の前に改行を入れてはいけません。
    改行するなら As の後に加えた方が良いでしょう。もしも As の前で改行したいなら、
    その前に行継続文字「 _」が必要なはずです。 (半角の空白とアンダーバー)
違反を報告
削除キー/

前の記事(元になった記事) 次の記事(この記事の返信)
←共変性と反変性ってこういうこと? /VBはじめました →Re[2]: 共変性と反変性ってこういうこと? /魔界の仮面弁士
 
上記関連ツリー

Nomalアイコン 共変性と反変性ってこういうこと? / VBはじめました (19/12/05(Thu) 13:36) #34410
Nomalアイコン 共変性と反変性ってこういうこと? / 魔界の仮面弁士 (19/12/06(Fri) 11:05) #34411 ←Now
  └Nomalアイコン Re[2]: 共変性と反変性ってこういうこと? / 魔界の仮面弁士 (19/12/06(Fri) 11:46) #34412
    └Nomalアイコン Re[3]: 共変性と反変性ってこういうこと? / VBはじめました (19/12/06(Fri) 23:46) #34413
      └Nomalアイコン Re[4]: 共変性と反変性ってこういうこと? / VBはじめました (19/12/06(Fri) 23:47) #34414 解決み!

All 上記ツリーを一括表示 / 上記ツリーをトピック表示
 
上記の記事へ返信

Mode/  Pass/


- Child Tree -