【发布时间】:2019-07-24 12:16:09
【问题描述】:
考虑以下测试程序,其中我(ab)使用字典来包含可能具有未知字段(以及这些字段的未知类型)的文档,
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
从集合的反序列化来看,循环中变异文档没有效果?这怎么可能?我错过了什么?我在循环中直接引用了文档对象...
【问题讨论】:
-
Dictionary
不是不可变的,即使 IEnumerable 可能是。 -
这在我看来可能是与
IEnumerable的延迟执行行为有关的问题。您是否尝试过创建文档的实际集合? (即类似var docs = GetDocuments().ToArray()) -
我希望它能够修改字典,这就是我在循环中所做的。它没有,我应该能够将引用类型的任何实例分配给该字典中的任何键(包括重新分配给新的引用类型)。
-
@bassfader 好像你是对的......强制它评估修复它,但我再次希望 newtonsoft 评估 IEnumerable
-
but then again I would expect newtonsoft to evaluate the IEnumerable它确实评估了可枚举。从而获得一组全新的Documents。注意 - 这与 newtonsoft 完全无关 - 如果您执行第二个foreach循环,您会看到完全相同。
标签: c# ienumerable