代码之家  ›  专栏  ›  技术社区  ›  Nick Heiner

查询之间不保留对IEnumerable的更改

  •  5
  • Nick Heiner  · 技术社区  · 14 年前

    IEnumerable 是一个延迟计算的查询。但显然我的理解有点缺陷。我希望以下几点能起作用:

            // e.Result is JSON from a server
            JObject data = JObject.Parse(e.Result);
            JsonSerializer serializer = new JsonSerializer();
    
            // LINQ query to transform the JSON into Story objects
            var stories = data["nodes"].Select(
                       obj => obj["node"]).Select(
                            storyData => storyOfJson(serializer, storyData));
    
            // set a value on each story returned by the query
            foreach (Story story in stories)
            {
                story.Vid = vid;
            }
    
            // run through the query again, making sure the value was actually set
            foreach (Story story in stories)
            {
                // FAILS - story.VID is 0
                Debug.Assert(story.Vid == vid);
            }
    

    我在这里有什么误会?如何更改此查询返回的结果?

    3 回复  |  直到 14 年前
        1
  •  11
  •   SLaks    14 年前

    每次你列举 stories Select 调用再次运行,创建一组新的 Story 物体。

    foreach 循环在另一组 实例。

    .ToArray() .
    循环遍历结果数组不会重新计算LINQ调用(因为它是一个普通数组),因此您将共享同一组 故事 实例。

        2
  •  1
  •   Billy ONeal IS4    14 年前

    IEnumerable 在这种情况下,包含 storyOfJson 在集合上重复调用,而不是原始值。

    当您在 foreach ,根据需要重复调用函数,并将函数调用的结果放入 迭代变量( story 在这种情况下)。

    如果你想储存 Story 对象,则必须先将它们放入某种形式的集合中,因为一旦循环终止,枚举项就会被销毁。

    var stories = data["nodes"].Select(obj => obj["node"]).Select(storyData => storyOfJson(serializer, storyData));
    

    变成

    var stories = from node in data["nodes"]
                  select storyOfJson(serializer, node["node"]);
    
        3
  •  1
  •   Merlyn Morgan-Graham    14 年前

    IEnumerable .Select(storyData => storyOfJson(...)) ,每次都会得到新对象。

    这意味着,如果编辑得到的副本,然后再次执行查询/调用get,那么您的更改将被删除。

    如果要编辑查询结果,请添加自己的 .Select()

    var filteredStoried = stories.Select(s => new Story(s) { Vid = vid });
    
    foreach(var s in filteredStories)
        Assert(s.Vid == vid);
    

    或者将查询结果复制到本地集合,并使用该集合:

    var localStories = new List<Story>(stories);
    
    foreach(var s in localStories)
        s.Vid = vid;
    
    foreach(var s in localStories)
        Assert(s.Vid == vid);