5

私は一生これを理解することはできません。次の 2 つの辞書オブジェクトがあるとします。

// Assume "query" is a LINQ queryable.
Dictionary<string, int> d1 = query.ToDictionary(k => k.Key, v => v.Value);
Dictionary<string, int>  d1 = query.ToDictionary(k => k.Key, v => v.Value);

次のステートメントは、Dictionary と IDictionary の間の暗黙的な変換ができないというコンパイル時エラーを生成します。

// Compile time error!
Tuple<IDictionary<string, int>, IDictionary<string, int>> = Tuple.Create(d1, d2);

私は明示的に変換を行う必要があります:

Tuple<IDictionary<string, int>, IDictionary<string, int>> = Tuple.Create(d1 as IDictionary<string, int>, d2 as IDictionary<string, int>);

コンパイラが共分散操作を理解できない理由を理解していません-DictionaryはIDictionaryを実装しています-特に、このようなものがもちろん機能するためです。

IDictionary<string, int> d3 = d1;

この動作には正当な理由があると確信しており、それが何であるかに興味があります。

更新 1: 明確にするために、問題を解決する方法ではなく、動作に興味があります。私はさまざまな解決策を認識しています:)

更新 2: すばらしい回答をありがとうございました。私はTuple不変であるとは知りませんでしたが、今ではそうです。

4

5 に答える 5

6

基本的に、問題は、Tupleファミリがその型引数で共変ではないことです。それはクラスなので、そうすることはできません。ただし、入力位置で型パラメーターを受け入れるメンバーがないため、共変であるインターフェースまたはデリゲートバージョンを作成できます。

これは次のように見るのが最も簡単Tuple<T1>です:

Tuple<string> stringTuple = Tuple.Create("Foo");
Tuple<object> objectTuple = stringTuple;

この呼び出し:

Tuple.Create(d1, d2);

...は両方の型引数をとして推論しているため、からに Dictionary<string, int>変換しようとしていますが、これは機能しません。Tuple<Dictionary<string, int>, Dictionary<string, int>>Tuple<IDictionary<string, int>, IDictionary<string, int>>

のバージョンでasは、型推論によって目的の型引数が得られるように引数の型が変更されていますが、Sebastianの回答に従って、型引数を直接記述し、推論を完全に回避する方が簡単です。

Tuple.Create<IDictionary<string, int>, IDictionary<string, int>>(d1, d2)

varこの時点で使用する場合、それほど悪くはありません。

var x = Tuple.Create<IDictionary<string, int>, IDictionary<string, int>>(d1, d2);

のタイプは、あなたが望むものになりますxTuple<IDictionary<string, int>, IDictionary<string, int>>

編集:コメントに記載されているように、その時点でコンストラクターを使用することもできます。

var x = new Tuple<IDictionary<string, int>, IDictionary<string, int>>(d1, d2);
于 2012-11-11T16:56:44.100 に答える
3

割り当てようとしています...

Tuple<Dictionary<string, int>, Dictionary<string, int>>

...に...

Tuple<IDictionary<string, int>, IDictionary<string, int>>

...しかし、これTuple<T1, T2>はクラスであるため、不変です。

于 2012-11-11T16:56:56.040 に答える
2

Tuple.Createのタイプパラメータはタイプから推測されるため、右側は2つのディクショナリのタプルであり、これはIDictionaryのタプルとは異なるタイプです-タイプパラメータをTuple.Createに明示的に追加すると、タイプになりますメソッドパラメータがより具体的なタイプであっても問題ないため、IDictionaryはすべて期待どおりに機能するはずです。

 Tuple.Create<IDictionary<string, int>,IDictionary<string, int>>(d1,d2)
于 2012-11-11T16:56:00.220 に答える
2

C#のクラス(したがってクラス)は共分散をサポートしていないため、aTuple<Dictionary<string, int>, Dictionary<string, int>>とaの間の変換はありません。Tuple<IDictionary<string, int>, IDictionary<string, int>>Tuple<T1, T2>

コンパイラーは、への呼び出しに対して最も具体的な戻り型の型を推測し、推測Tuple.Create中に左側の型を使用しません。

于 2012-11-11T16:56:49.437 に答える
0

変数の型を からDictionary<string, int>に変更してみてくださいIDictionary<string, int>.

IDictionary<string, int> d1 = query.ToDictionary(k => k.Key, v => v.Value);
IDictionary<string, int>  d1 = query.ToDictionary(k => k.Key, v => v.Value);
于 2012-11-11T16:49:55.720 に答える