2

IDictionary<TKey, IList<TValue>>オブジェクトをにキャストするのはかなり簡単だと思いますIDictionary<TKey, IEnumerable<TValue>>が、

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

をスローしSystem.InvalidCastException

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

valnullにします。これをキャストする適切な方法は何ですか?

4

2 に答える 2

8

IDictionary<TKey, IList<TValue>>オブジェクトをにキャストするのはかなり簡単だと思いますIDictionary<TKey, IEnumerable<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"];

ご覧のとおり、これは問題を引き起こします。LinkedList<int>すべての値が実装されることを期待しているときに、問題を解決しようとしていますIList<int>。ジェネリックスのポイントはタイプセーフであることです-では、どの行が失敗すると予想しますか?1行目、3行目、4行目は、私には非常に明確に有効に見えます。したがって、2行目は、コンパイルに失敗する可能性がある唯一の行です。

これで、場合によっては、安全に実行できます。たとえば、「出力」位置でのみ使用されるため、(C#4では)からIEnumerable<string>に変換できます。IEnumerable<object>IEnumerable<T>T

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

編集:明確にするために-既存のキーと値のペアのコピーを使用して新しい辞書を作成するのは簡単です。たとえば、リンクを使用します。

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

2つの別々の辞書があることに注意する必要があります。

于 2012-05-01T15:03:51.407 に答える
0

これはあなたを助けるかもしれないし、助けないかもしれませんが、私はジョンの答えの補足としてそれを捨てると思いました。

キーを参照せずに辞書の値だけが必要な場合は、次のように実行できます。

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;
于 2012-05-12T00:46:11.143 に答える