将KeyValuePair的LINQ结果列表强制转换为字典 - 缺少概念

时间:2010-12-31 14:18:41

标签: c# linq list dictionary

我想写这个LINQ语句:

Dictionary<int, ItemBO> result = ( Dictionary<int, ItemBO> )
    ( from item in originalResults where item.Value.SomeCriteria == true
    select item );

originalResults的类型为Dictionary<int, ItemBO>

我认为item的类型为KeyValuePair<int, ItemBO>,但我认为从该类型的列表转换为该类型的词典会是......呃......“天然的”。

相反,为了让编译器闭嘴,我需要写一下:

Dictionary<int, ItemBO> result = 
    ( from item in originalResults where item.Value.SomeCriteria == true
    select item.Value ).ToDictionary( GetItemKey );

虽然并非完全违反直觉,但它表明,正在进行大量不必要的工作,打包和重新打包字典。有更好的解决方案吗?我错过了一个概念吗?

4 个答案:

答案 0 :(得分:4)

  

虽然并非完全违反直觉,但它表明,正在进行大量不必要的工作,包括解包和重新包装词典。

我不确定“不必要的”工作是什么意思。要执行此操作需要大量工作 - 必须对查询进行全面评估,这涉及扫描整个字典并评估每个条目的谓词。此外,必须创建并填充新字典以存储结果。我认为如果通过自动转换隐藏这项工作会更有问题。

真正的问题是你向后使用你的字典。按键查找速度很快,但按值查找需要扫描字典中的所有项目。如果您可以存储字典,以便您用来过滤的值是关键,那么您将能够更快地查找并使用更清晰的语法。

答案 1 :(得分:2)

我将再次尝试你所缺少的真正的“关键”概念。

如果我想冒险,我会说我认为你想象一个Dictionary<TKey, TValue>作为其内容的同义词。 你有一堆键值对 - 这是一本字典,对吗?这就是你错过重要细节的地方。虽然你肯定可以使用简单的IDictionary<TKey, TValue>来实现KeyValuePair<TKey, TValue>[],但这将缺少首先使用字典类型的最大好处之一:快速查找按键。

即使您对数组进行了排序并使用二进制搜索来定位键(顺便说一下,这会导致所有插入的成本),您也无法与Dictionary<TKey, TValue> {{1}}竞争使用。这种实现不仅仅是“一堆键值对”,没有特定的结构;结构是此类型的所有。因此,从一堆键值对(没有结构的内容)直接到字典(具有非常特殊的结构)的快速转换实际上是不可能的 - 不是类型的结构布局确实确定是否可以在无论如何C#(你必须单独遵守继承,并且一些内置的,可能还有用户定义的类型转换)。

这样想:字典是容器,而不是内容,对吧?所以,如果我有一罐不同类型的饼干,我想要拿出所有巧克力饼干,我可能会提取每一个,把它们全部放在一堆然后说:“现在这是一罐巧克力芯片饼干,对吧?“不,我只把饼干拿出来;我拥有的是一堆,而不是一个罐子。如果我想要巧克力饼干的 jar ,那么我将将它们放在一个中 - 这将需要一些非零工作量。

答案 2 :(得分:1)

您缺少的概念是您的代码代表现有字典的查询,其结果将是IEnumerable<KeyValuePair<K,V>>。您的原始代码期望的是有人定义了IEnumerable<KeyValuePair<K,V>>Dictionary<K,V>的转化。从本质上讲,他们已经让你能够定义自己需要的任何转换,因为你有ToDictionary扩展方法,可以让你确定一个键,一个值等。

答案 3 :(得分:0)

linq查询的“真实”结果不是字典,因此您无法自然地进行转换。 结果是IQueryable,所以你必须明确地转换它。