8

.NET ジェネリック型のキャストで何かが得られません。誰かが次のコード スニペットで何が起こるか説明できますか?

void Main()
{
    IEnumerable<int> ints = new List<int>();
    IEnumerable<string> strings = new List<string>();

    var rez1=(IEnumerable<object>)ints; //runtime error
    var rez2=(IEnumerable<object>)strings; //works
    var rez3=(List<object>)strings; //runtime error
}
4

3 に答える 3

11

最も簡単な2行目から始めましょう。

IEnumerable<T>の型パラメーターが共変であるため、このキャストは機能します(これがoutinのout T機能です)。IEnumerable<Derived>これは、をIEnumerable<Base>自由にキャストできることを意味します。

int同じ場合のように見える最初の行は、値型であるため機能しません。System.Object値型は実際には;から継承しないため、インターフェイスの差異は値型ではまったく機能しません。それらはボックスに入れることができますobjectが、それは同じではありません。ドキュメントには次のように記載されています

差異は参照型にのみ適用されます。バリアント型パラメーターに値型を指定すると、その型パラメーターは、結果として作成される型に対して不変になります。

List<T>最後に、のタイプパラメータが不変であるため、3行目は機能しません。outタイプパラメータに何もないことがわかります。List<T>はインターフェースではないため、ルールはそれを許可していません。

.NET Framework 4では、バリアント型パラメーターはジェネリックインターフェイスとジェネリックデリゲート型に制限されています。

于 2012-09-11T18:00:16.863 に答える
2

これは、インターフェースの共分散が参照型でのみ機能するためです。もちろん、Int32は値型です。

これにより、詳細情報が得られます:http: //blogs.msdn.com/b/ericlippert/archive/2009/11/30/what-s-the-difference-between-covariance-and-assignment-compatibility.aspx

そしてこれもそうです: http: //ericlippert.com/2011/09/19/inheritance-and-representation/

于 2012-09-11T17:59:37.340 に答える
0

から派生するすべての型の定義はSystem.ValueType、 を除いてSystem.Enum、実際には 2 種類のものを定義します: ヒープ オブジェクト型とストレージ ロケーション型です。後者のインスタンスは暗黙のうちに前者に変換され (そこに含まれるデータのコピーを作成)、前者のインスタンスは明示的に後者に型キャストされます (同様に)。どちらの種類のものも同じSystem.Typeで記述され、メンバーは同じですが、動作が大きく異なります。

AList<AnyClassType>は、一連のヒープ オブジェクト参照を保持することを期待します。問題のリストがList<String>List<StringBuilder>List<Button>、またはその他のものであるかどうかは、リストのユーザーにとっては興味深いかもしれませんが、実際にはList<T>それ自体には興味がありません。List<Button>aを anにキャストすると、IEnumerable<Control>そのメソッドを呼び出す人は、GetEnumerator()から派生したヒープ オブジェクトへの参照を出力するオブジェクトを取得することを期待しますControl。からのリターンはList<Button>.GetEnumerator()その期待を満たします。対照的に、誰かが to をキャストした場合、List<Int32>呼び出しList<Object>た人GetEnumerator()は、ヒープ オブジェクト参照を出力するものを期待しますが、List<Integer>.GetEnumerator代わりに値型の整数を出力するものを生成します。

Int32値を aList<Object>または aに格納することができList<ValueType>ます。このようなリストに整数を格納すると、それがヒープ オブジェクト形式に変換され、それへの参照が格納されます。を呼び出すGetEnumerator()と、ヒープ参照を出力するものが生成されます。ただし、そのようなリストに に対応するヒープ タイプのインスタンスのみが含まれるように指定する方法はありませんInt32。C++/CLI では、「ヒープ格納値型への参照」型の変数を宣言できますが、.net のジェネリック型の背後にあるメカニズムは、そのような型では機能しません。

于 2013-01-21T18:41:28.007 に答える