2012-05-01 17 views
1

私はそれがIDictionary<TKey, IEnumerable<TValue>>IDictionary<TKey, IList<TValue>>オブジェクトをキャストすることは非常に簡単だと思うだろうが、入れ子のインターフェイス:IDictionary <TKey、IEnumerable <TValue>>にIDictionary <TKey、IList <TValue>>をキャストしますか?

var val = (IDictionary<TKey, IEnumerable<TValue>>)Value; 

System.InvalidCastExceptionをスローし、

var val = Value as IDictionary<TKey, IEnumerable<TValue>>; 

valヌルになります。これをキャストする正しい方法は何ですか?

答えて

7

私はそれがIDictionary<TKey, IEnumerable<TValue>>

絶対にしないようにIDictionary<TKey, IList<TValue>>オブジェクトをキャストすることは非常に簡単だと思うだろう。タイプセーフではありません。ここでは、なぜないの例です:

// This is fine... 
IDictionary<string, IList<int>> dictionary = new Dictionary<string, IList<int>>(); 

// Suppose this were valid... 
IDictionary<string, IEnumerable<int>> badDictionary = dictionary; 

// LinkedList<T> doesn't implement IList<T> 
badDictionary["foo"] = new LinkedList<int>(); 

// What should happen now? 
IList<int> bang = dictionary["foo"]; 

あなたが見ることができるように、それは問題を起こすために起こっている - 私たちはすべての値がIList<int>を実装することを期待するときLinkedList<int>アウトを取得しようとするだろう。ジェネリックのポイントはタイプセーフなので、どのラインが失敗すると思いますか?第1、第3、第4行は、私にはかなり明確に有効に見える - そうもう一つはコンパイルに失敗することができる唯一のあり、そしてそれは...

今すぐ一部例では、それができるん安全に完了しました。たとえば、IEnumerable<string>からIEnumerable<object>に変換するには、IEnumerable<T>は "出力"の位置にTしか使用しないので、(C#4では)変換できます。

詳細はMSDNを参照してください。

EDIT:明らかにするために、新しい辞書を既存のキーと値のペアのコピーで簡単に作成できます。リンクを使用して:

var copy = original.ToDictionary<TKey, IEnumerable<TValue>>(pair => pair.Key, 
                  pair => pair.Value); 

あなたは今すぐ別々の2つの辞書があることに気づく必要があります。

+0

これは私には意味がありません。 'IEnumerable <>'は 'IList <>'から継承しませんが、これは逆です。明らかに間違っているようです。子孫ではなく、祖先としてキャストできますか?だから、それはどのようにダウンキャスティングを無効にしますか? –

+0

@JeremyHolovacs:私の例はあなたがしたいことを*正確に*しようとしました: 'IDictionary >を' IDictionary > 'に変換してください。それがあなたがしたいことでない場合は、あなたの質問を明確にする必要があります。 –

+0

最後の行はまったく同じようには見えません。あなたは 'IEnumerable 'を 'IList 'に変換しようとしているようで、明らかに間違っているようです。 'IList'が' IEnumerable'から継承しているので、 'IList 'を 'IEnumerable 'に変換するのは、完全に正当なものでなければなりません。 –

0

これはあなたを助けるかもしれないし、役に立たないかもしれませんが、私はJonの答えの補足としてそれを捨てると思っていました。

あなたが必要とするすべては自分のキーを参照することなく、あなたがこれを行うことができ、辞書のの場合:作業には、このために

IDictionary<TKey, IList<TValue>> dictionary = Whatever(); 
var values = (IEnumerable<IEnumerable<TValue>>)dictionary.Values; 

を、あなたは、C#4.0以降を使用して、TValueしなければならない必要があります参照型に制約される可能性があります。ここにコードがあり、若干リファクタリングされ、説明するコメントがあります。

IDictionary<TKey, IList<TValue>> dictionary = Whatever(); 

//Values returns an ICollection<IList<TValue>> 
ICollection<IList<TValue>> temp1 = dictionary.Values; 

//ICollection<T> inherits from IEnumerable<T> 
IEnumerable<IList<TValue>> temp2 = temp1; 

//IEnumerable<T> is covariant 
//There is an implicit reference conversion between IList<T> and IEnumerable<T> 
//So there is an implicit reference conversion between IEnumerable<IList<T>> 
//and IEnumerable<IEnumerable<T>> 
IEnumerable<IEnumerable<TValue>> values = temp2; 
関連する問題