【问题标题】:Linq: Select with and without ToList() [duplicate]Linq:选择有和没有 ToList() [重复]
【发布时间】:2019-01-31 13:43:26
【问题描述】:

谁能解释这种行为?

此代码有效:

Dictionary<string, int> fullPathTabAssociation = new Dictionary<string, int>();

    //bla bla.. 
    //here fullPathTabAssociation is populated
    ////bla bla.. 

var newValues = fullPathTabAssociation
  .Where(x => x.Value > index)
  .Select(x => new KeyValuePair<string, int>(x.Key, x.Value - 1))
  .ToList();

fullPathTabAssociation.Clear();

/*now newValues is populated with correct values*/

此代码不起作用

Dictionary<string, int> fullPathTabAssociation = new Dictionary<string, int>();

    //bla bla.. 
    //here fullPathTabAssociation is populated
    ////bla bla.. 

var newValues = fullPathTabAssociation
  .Where(x => x.Value > index)
  .Select(x => new KeyValuePair<string, int>(x.Key, x.Value - 1))

fullPathTabAssociation.Clear();

 /*now newValues is empty*/

select 函数似乎返回一个新的IEnumerable,在fullPathTabAssociation.Clear() 之前进行调试,在这两种情况下,newValues 的值都是正确的,并且与fullPathTabAssociation 不同。特别是我不明白最后一种情况会发生什么

【问题讨论】:

  • Linqlazy 它只在 materialization (.ToList()) 上工作。
  • A(延迟执行)LINQ 查询只是一个查询。它描述了检索您想要的内容必须执行的操作。它尚未执行。如果您附加ToList,则您实现此查询并将结果填充到列表中。您的查询的来源是字典,如果您清除它,查询将不会返回任何内容。如果先将结果填充到列表中,则由于列表未与字典耦合,因此清除字典不会清除此结果。
  • 谢谢,我一直在寻找延迟行为

标签: c# linq pointers function-pointers


【解决方案1】:

Linq 是 懒惰的;它尽可能地推迟其工作(最多 foreach 或某种物化)。

在第一个摘录中,您使用 .ToList() 实现查询,这里 Linq 必须执行并提供 List&lt;T&gt; 集合:

var newValues = fullPathTabAssociation
  .Where(x => x.Value > index)
  .Select(x => new KeyValuePair<string, int>(x.Key, x.Value - 1))
  .ToList(); // <- Materizataion an actual List<T> required; Linq executes 

// Since we have newValues collection (not query) it doesn't depend on аullPathTabAssociation
fullPathTabAssociation.Clear();

在第二个摘录中,Linq 不需要做任何事情

// Just a query, no materialization
var newValues = fullPathTabAssociation
  .Where(x => x.Value > index)
  .Select(x => new KeyValuePair<string, int>(x.Key, x.Value - 1));

fullPathTabAssociation.Clear();

...

// Only here (on foreach or materialization) Linq has to execute the query; 
// and it takes fullPathTabAssociation (which is empty) 
foreach (var item in newValues) {
  ...
}

【讨论】:

    【解决方案2】:

    不同之处在于,通过使用ToList,您正在执行 Linq 查询并创建新列表。这个新创建的列表的内容独立于fullPathTabAssociation

    在第二个示例中,您只将查询存储在newValues 中。查询尚未执行,只有在您清除查询源后才会执行。因此,查询结果为空。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2015-03-04
      • 1970-01-01
      • 2021-12-09
      • 2020-01-11
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多