c#linq func式内のienumerableに関するc#ハッシュセットユニオンは機能しません(precompilerバグの可能性)
質問
Microsoft .NETフレームワーク4.0を使用しています。
私はaの集合体を使用してこれに遭遇しました Dictionary<T, List<T>>
タイプのセットを抽出します T
すべてのタイプで使用される値 List<T>
辞書のリスト。これが私が同じ動作を示すことを考え出すことができる最も簡単なケースです。
まず、 ドキュメンテーション 州、以下 します 仕事:
var set = new HashSet<int>();
var list = new LinkedList<int>();
var newSet = set.Union(list);
つまり、電話することができます Union
aで HashSet
とともに List
議論として(それは実装されているので IEnumerable
).
一方、a内の同等の式 Func
linqの議論 Aggregate
式はエラーを生成します(少なくともプレキサラー):
new List<int>[] { new List<int>() }.Aggregate(new HashSet<int>(), (acc, list) => acc.Union(list));
それは、ユニオンの議論がハッシュセットであると予想しており、Linq/FUNC式以外の行動に反して、それが与えられた場合に協力します。
問題に出会ったときに使用していた現実世界の例は、次のとおりです。
public AdjacencyListGraph(Dictionary<TVertex, LinkedList<TVertex>> adjacencyList)
{
var vertices = adjacencyList.Aggregate(new HashSet<TVertex>(),
(vertices, list) => vertices.Union(list.Value));
}
変換できないと不平を言っています IEnumerable<TVertex>
に HashSet<TVertex>
...
解決
問題は、実際には、アキュムレータタイプのハッシュセットをIENUMERABLEで置き換えようとすることにあります。ユニオンメソッドはハッシュセットにアイテムを追加しませんが、結果の結合で新しいIENUMERABLEを返します。
コードを次のように変更する必要があります。
// select from keys
var vertices = new HashSet<TVertex>(adjacencyList.Keys);
また
// select from values
var vertices = new HashSet<TVertex>(adjacencyList.SelectMany(dictEntry => dictEntry.Value));
他のヒント
ここでの問題は、あなたの理解にあります Select
方法。渡されたラムダは、リストを受け取るのではなく、リストの要素を受け取ります。したがって、あなたが名前を付けた変数 list
実際にはタイプです int
互換性がありません Union
.
これがあなたがやろうとしていることのより明確な例です
new List<int>().Select( (int list) => new HashSet<int>().Union(list));
タイプの推論が削除されたため、これが機能しない理由ははるかに明確です。
new List<int>().Select(list => new HashSet<int>().Union(list));
あなたが使用することを期待すると思います SelectMany
ここで、結果がそうであることを望まない限り IEnumerable<IEnumerable<T>>
.