なぜ最後の行が許可されないのですか?
doubleは値型でオブジェクトは参照型なので、共分散は、両方の型が参照型である場合にのみ機能します。
doubleはオブジェクトから派生しない値型なので、共分散は機能しませんか?
いいえダブルはオブジェクトから派生します。すべての値の型はオブジェクトから派生します。
今あなたが求めている必要があります質問:
はなぜ共分散はIEnumerable<object>
にIEnumerable<double>
を変換するために動作しませんか?
誰がボクシングを行うのですか?ダブルからオブジェクトへの変換はボックスダブルでなければなりません。 IEnumerator<object>.Current
への呼び出しが、実際にはIEnumerator<double>.Current
の実装への呼び出しであるとします。呼び出し元は、オブジェクトが返されることを期待します。着呼者は二重を返す。 IEnumerator<double>.Current
によって返されたdoubleをボックス化されたdoubleに変換するボクシング命令を実行するコードはどこですか?
ここではですが、これがこの変換が違法な理由です。 Current
を呼び出すと、評価スタックに8バイトの倍精度値が設定され、コンシューマは評価スタックのボックス化された倍精度浮動小数点型への4バイト参照を期待します。そのため、消費者はひどくクラッシュし、スタックが整列しておらず、無効なメモリを参照しています。
あなたはにボックスがを実行するコードが必要な場合、それはは、いくつかの点でを書かなければならず、そしてあなたはそれを書くことを得る人です。
IEnumerable<object> objects2 = doubleenumerable.Cast<object>();
今、あなたが参照に、ダブル8バイトからダブルに変換ボクシングの命令が含まれているヘルパーメソッドを呼び出します。最も簡単な方法は、Cast<T>
拡張メソッドを使用することです。
UPDATE:私が質問したことを覚えていることを注釈者が指摘しています。つまり、元の質問の解決策として難しい問題を解決する仕組みが存在することを前提に質問に答えました。 Cast<T>
の実装は、ボックスにするかどうかを知るという問題をどのように解決することができますか?
このスケッチのように機能します。
public static IEnumerable<T> Cast<T>(this IEnumerable sequence)
{
if (sequence == null) throw ...
if (sequence is IEnumerable<T>)
return sequence as IEnumerable<T>;
return ReallyCast<T>(sequence);
}
private static IEnumerable<T> ReallyCast<T>(IEnumerable sequence)
{
foreach(object item in sequence)
yield return (T)item;
}
オブジェクトからTへのキャストがアンボクシング変換、または基準変換がランタイムに延期されたか否かを決定するための責任:パラメータタイプはないジェネリックであることに留意されたいです。ジッタは、Tが参照型であるか値型であるかを知る。 99%の時間はもちろんリファレンスタイプになります。
[なぜ共分散と反差異が値型をサポートしないのか](http://stackoverflow.com/questions/12454794/why-covariance-and-contravariance-do-not-support-value-type) – nawfal