为什么不能在IEnumerable循环内修改属性包(Dictionary <string,object>)

时间:2019-07-24 12:16:09

标签: c# ienumerable

请考虑以下测试程序,在该程序中,我(ab)使用字典来包含可能具有未知字段(以及这些字段的类型未知)的文档,

Fiddle of the program

using System;
using System.Linq;
using System.Collections.Generic;
using Newtonsoft.Json;

public class Program
{
    public static void Main()
    {
        var docs = GetDocuments();
        foreach(var doc in docs){
            doc["a"] = new string[]{"Hello", "World!"};
            var docInLoop = JsonConvert.SerializeObject(doc);
            Console.WriteLine(docInLoop);
        }

        var serialized = JsonConvert.SerializeObject(docs);
        Console.WriteLine("===========================================================================================");
        Console.WriteLine(serialized);
        Console.WriteLine("===========================================================================================");
        var bar = docs.First()["a"] as string[];        
        Console.Write("First entry of first document is string[]?");
        Console.WriteLine(bar==null? " No" : "Yes");


    }

    public static IEnumerable<Document> GetDocuments(){
        return Enumerable.Range(0, 10).Select(i => {

        var doc = new Document();
        doc["a"] = new int[]{1,2,3,4,5,6};
        return doc;
        });
    }

    public class Document : Dictionary<string, object>{}
}

运行此命令时,由于在foreach循环中我修改了文档,因此应该修改文档集合。但是这是输出:

{"a":["Hello","World!"]}
{"a":["Hello","World!"]}
{"a":["Hello","World!"]}
{"a":["Hello","World!"]}
{"a":["Hello","World!"]}
{"a":["Hello","World!"]}
{"a":["Hello","World!"]}
{"a":["Hello","World!"]}
{"a":["Hello","World!"]}
{"a":["Hello","World!"]}
===========================================================================================
[{"a":[1,2,3,4,5,6]},{"a":[1,2,3,4,5,6]},{"a":[1,2,3,4,5,6]},{"a":[1,2,3,4,5,6]},{"a":[1,2,3,4,5,6]},{"a":[1,2,3,4,5,6]},{"a":[1,2,3,4,5,6]},{"a":[1,2,3,4,5,6]},{"a":[1,2,3,4,5,6]},{"a":[1,2,3,4,5,6]}]
===========================================================================================
First entry of first document is string[]? No

从反序列化的集合来看,在循环中更改文档没有效果?这怎么可能?我想念什么?我在循环中直接引用了文档对象...

1 个答案:

答案 0 :(得分:3)

  

我在循环中直接引用了文档对象...

不,你不知道。您可以参考有关如何制作此数据的方法! 这就是推迟执行的目的。

实际上是第一次在此行中执行查询:

foreach(var doc in docs){

这是您第一次煮饭。您可以用自己的食材很好地调味。

在此行中序列化doc时:

var serialized = JsonConvert.SerializeObject(docs);

您基本上将再次执行GetDocuments中的查询。就像您写的一样:

var serialized = JsonConvert.SerializeObject(GetDocuments());

这基本上意味着您要再次做饭。遵循食谱,但是这次您没有添加任何成分作为上一次。然后您想知道为什么汤的味道不像您第一次放入的香料。

如果在循环之前使用ToList()调用来实现结果,则会得到所需的结果:

var docs = GetDocuments().ToList();

这是一个很好的article,详细介绍了deferred execution的陷阱