1. ホーム
  2. c#

[解決済み] 共分散と共分散が値型をサポートしない理由

2022-04-26 15:27:41

質問

IEnumerable<T> 共変数 が、値型をサポートしておらず、参照型のみです。以下の簡単なコードは正常にコンパイルされます。

IEnumerable<string> strList = new List<string>();
IEnumerable<object> objList = strList;

しかし string から int を実行すると、コンパイルエラーが発生します。

IEnumerable<int> intList = new List<int>();
IEnumerable<object> objList = intList;

で説明しています。 MSDN :

Variance は参照型にのみ適用されます。Variant 型パラメータに値型を指定すると、その型パラメータは結果として構築される型に対して不変になります。

検索してみたところ、いくつかの質問で、その理由を述べているのは 値型と参照型の間のボックス化 . しかし、なぜボクシングが理由なのか、まだよく分かっていないのです。

どなたか、共分散と共分散が値型をサポートしない理由をわかりやすく丁寧に説明してください。 ボクシング というのはどういうことでしょうか?

解決方法は?

基本的に、分散はCLRがいかなる 表現上の変更 を値に追加します。参照はすべて同じに見える。 IEnumerable<string> として IEnumerable<object> ネイティブコード自身は、インフラが確実に有効であることを保証している限り、あなたが値に対して何をしているかを知る必要は全くありません。

値型の場合、それはうまくいきません。 IEnumerable<int> として IEnumerable<object> の場合、シーケンスを使用するコードは、ボクシング変換を実行するかどうかを知る必要があります。

Eric Lippert の 表現と同一性についてのブログ記事 をご覧ください。

EDIT: Ericのブログ記事を自分で読み直してみると、少なくとも、この記事は アイデンティティ とはいえ、この2つはリンクしています。特に

このため、インターフェイス型やデリゲート型の共変換や共変換では、変化する型引数がすべて参照型であることが要求されます。変化する参照変換が常に同一性保持であることを保証するために、型引数を含む変換のすべてもまた同一性保持でなければなりません。型引数のすべての非自明な変換が同一性保持であることを保証する最も簡単な方法は、それらを参照変換であるように制限することです。