2017-01-23 5 views
5

最初のケースでは型変換ができない理由を理解しようとしていますが、2番目のケースでは可能です。下記のコードをご覧ください:C#でのジェネリックリストの型変換

var strList = new List<string>{"One", "Two", "Three"}; 
List<object> objList = (List<object>) strList; // <<<< why is not converted? - Case 1 

IEnumerable<object> ienumList = strList; // <<<< why is converted? - Case 2 
+5

共分散と反動を見てください。 – HimBromBeere

+1

http://stackoverflow.com/questions/16966961/cannot-convert-from-listderivedclass-to-listbaseclassまたはhttp://stackoverflow.com/questions/1817300/convert-listderivedclass-to-listbaseclassを参照してください。 – wkl

+1

s.th.をまだやりたいのであれば。 'List 'へのキャストと同様に、 'OfType' od' Cast 'を使用することができます – wkl

答えて

-1

共変および異モンドの説明については、以下を参照してください。それはあなたが持つ問題についての明快さを与えるだろうと思う:

http://tomasp.net/blog/variance-explained.aspx/

+2

ここでは、リンクのみの回答が表示されます。おそらく、そのページの関連する詳細を含めるように答えを更新することはできますか? – Chris

0

あなたは、フレームワーク3.5以降を使用している場合は、あなたがこれを行うことができます:

var strList = new List<string>{"One", "Two", "Three"}; 
List<object> objList = strList.Cast<object>().ToList(); 

あなたは@Hagashen Naiduを見てみることができますこの場合は非常に良い説明があります。

+1

これはコードワードの行を作る方法を提供しますが、実際にその振る舞いがそのままである理由の質問には実際には答えません。 – Chris

+1

@Chrisあなたは正しいです。私の悪い。それでも誰かを助けるかもしれないので、答えをそのまま残しておきます。 – NicoRiff

9

comment referring to covariance and contravarianceが基本原理についての良い点を行っている間、私が提示した場合の具体的な効果の点でお答えするつもりです:

List<object> objList = (List<object>) strList; 

objListが書き込み可能です。それはあなたがこれを行うことができます:

objList.Add(new Object()); 

はしかし、objListはまだstrListと同じインスタンスです。 List<string>System.Objectのインスタンスを追加しました。

コンパイラは、そのことを許可できません。したがって、List<string>List<object>にキャストできません。第2のケースで

は、他の一方で、あなたが列挙を取得: IEnumerable<T>はインスタンスを変異任意のメンバーを提供しないよう

IEnumerable<object> ienumList = strList; 

は、結果の列挙を変更する方法はありません。したがって、型パラメータTには、outキーワードを付けることができます(これは)、提示された型キャストを可能にします。

2

ここでは、2つの主要な概念が役割を果たす:Type ConversionsおよびGeneric Interfaces Varianceです。分散が先行する場合。

ケース1:List<T>クラス定義では、汎用パラメータには差がありません。したがって、List<object>List<string>の間に定義された関係はありません。彼らは不変です。したがって、暗黙的および明示的な両方の型変換は不可能です。

ケース2:

分散をList<T>に許可されますが、IEnumerable<T>のために許可されていない理由:List<T>はそうList<string>が暗黙のうちにIEnumerable<object>

DETAILSにキャストすることができ、共変ジェネリック型であるIEnumerable<out T>を実装?

ジェネリックのポイントは、コンパイル時の安全性を提供することです。 List<T>ので書き込み可能でないとコンパイル時のチェックがなかった場合、我々は次のように書いて、実行時エラーが発生している可能性があり:

List<string> stringList = new List<string>(); 
stringList.Add("some string"); // we are safe 
List<object> objectList = stringList; 
objectList.Add((new Object()); // Aargh! 
// we are trying to put an object to a list of strings! 

List<T>ためだから、何の危険な分散。

ただし、IEnumerable<out T>は読み取り専用です。参照されるインスタンスを変更する方法はありません。

IEnumerable<object> objectList = new List<string>(); 
// we can't add a string to the objectList, 
// as `IEnumerable<out T>` is a read-only interface. 

したがって、安全な分散が可能です。

+0

こんにちはKalitsov。私はコードマークアップであなたの答えを編集する自由を取ったので、ちょっと丁寧で(文法の訂正もいくつか)将来自分自身でこれを行うには、コードとしてマークしたいテキストをバッククォート( '')で囲む必要があります。これはコードとしてレンダリングし、時には '<>'によって混乱することはありません。コードマークアップ。 – Chris

+0

クリスおかげさま!私はそれをやる方法をさまよっていた。 – Kalitsov

+0

エディターもこれを行います。段落内のテキストを強調表示して(全段落ではなく)上部のコードボタン( '{}'のように見える)を押すと、バッククォートに入れられます。 – Chris

関連する問題