ブログ「サイバー少年」

ブログ「サイバー少年」へようこそ!
小学六年生ごろからプログラミングを趣味にしている高校生のブログです。
勉強したことについての記事などを書いています。フリーソフトも制作、公開しています。
(当ブログについて詳しくは「ブログ概要紹介」を参照)

サイバー少年が作ったフリーソフトは「サイバー少年の作品展示場」へ

C#のout引数は型の反変性をサポートしない

C#で

void Method(string arg)Method(object変数) で呼び出すことは不可能ですが、
void Method(object arg)Method(string変数) で呼び出すことは可能です。

後者はアップキャストを行っています。
前者は、argにnew object()とかが入ってきたら困るので、不可能になっています。

次に、 void Method(ref string arg)Method(ref object変数) で呼び出すことは不可能です。

そして、 void Method(ref object arg)Method(ref string変数)で呼び出すことも不可能です。

前者が不可能な理由は先ほどと同じですが、

後者がなぜ先ほどと違うのかというと、参照渡しの場合は呼び出し元の変数を書き換え可能ですから、
Method内で arg = new object(); とか出来るわけですが、そうした場合に、Methodを呼び出した側からしてみればstring変数にnew object()が入っていることになってしまうからです。



では、 void Method(out string arg)Method(out object変数) で呼び出すのはどうなのかというと、不可能です。

そして、 void Method(out object arg)Method(out string変数) で呼び出すことも不可能です。

この後者が不可能である理由は、refの場合に同じことができない理由と同じです。

しかし前者が不可能である理由はありません。


どうせargにstring型以外の値が入ってきても、Method内部ではargは未初期化の変数として扱われるからです。

そして、Method内部でargに何を設定しようと、object型は上位互換ですから、全く問題がないはずなのです。


要するに、普通の引数は共変的、ref引数は不変的、out引数は反変的なのです。

しかし、C#はout引数の反変性をサポートしていないのです。
サポートするべきじゃないかと思うのです。




少し別の話題になりますが、
C#ではジェネリックなインターフェースやデリゲートの型引数に対して、共変性や反変性の指定を出来るようになりました。

“型A→型B”方向への互換性があるとき、

Class<out A>と定義されているなら“Class<A>→Class<B>”方向の互換性がありますし、

Class<in A>と定義されているなら“Class<B>→Class<A>”方向の互換性があります。


ただ、“型A→型B”方向の互換性があるとみなされるのは、“型A⊆型B”の継承関係があるときだけみたいです。

これは条件が狭すぎじゃないかと思います。

“型A→型B”方向の暗黙的な変換演算子が用意されているなら、それは“型A→型B”方向への互換性が存在するということにしていいんじゃないかと思うんですよね。

しかし、

ジェネリクスの共変性・反変性 (C# によるプログラミング入門)
http://ufcpp.net/study/csharp/sp4_variance.html#value

によるとILの実装上の制約で、値型の場合は上記のような継承関係があったとしても互換性があるとみなせないようですから、

もしかしたら、中の人の都合で、私が述べているような器用なことも出来ないのかもしれません。




共変性、反変性について調べてみたら、C#は共変性、反変性において物足りない部分が多かったので記事にしてみました。

もともとは、Nullable<int>型の変数を Method(out int arg) 的なメソッドに引数として与えたかったのに、エラーになったことから始まりました。

Nullable<int>を入れられたらかなり便利なんですけどね~。


共変性、反変性について調べたてホヤホヤの状態で書いたので、理解に誤りがあるかもしれませんが、その場合はぜひご指摘ください。

tag: C# 引数 out引数 共変性/反変性 ジェネリックス

コメント

コメントの投稿

トラックバック

トラックバック URL
http://cyberboy6.blog.fc2.com/tb.php/366-3eb4cca2
この記事にトラックバックする(FC2ブログユーザー)

当ブログをご利用(閲覧等)になる場合は必ず「当ブログの利用規定」をお守りください。