如何向ExpandoObject添加新数组元素?解决foreach循环中值被覆盖的问题
如何将二维数组元素全部添加到ExpandoObject集合而不被覆盖?
我现在需要把二维数组myArr中的所有值都添加到ExpandoObject类型的myObj里,期望生成一个包含所有元素对应对象的集合。我写了下面这段代码:
int[,] myArr = { {1, 2}, {3, 4} }; dynamic myObj = new ExpandoObject(); foreach(var myInt in myArr) { myObj.Ints = new[] { new { value = myInt, value_plus_1 = myInt + 1 } }; }
原本期望循环结束后,myObj.Ints的结构是这样的:
Ints: [
{ value: 1, value_plus_1: 2 },
{ value: 2, value_plus_1: 3 },
{ value: 3, value_plus_1: 4 },
{ value: 4, value_plus_1: 5 }
]
但实际每次循环都会覆盖上一次的结果,最后只得到:
Ints: [ { value: 4, value_plus_1: 5 } ]
请问我该怎么修改代码才能实现预期效果?
解决方案
嘿,问题出在你每次循环都在重新创建新数组并直接覆盖myObj.Ints,而不是往已有的集合里追加元素。这里有几种实用的修改方案:
方案一:先收集元素再赋值(最直观)
先把所有需要的对象存入一个列表,最后一次性赋值给myObj.Ints,避免每次覆盖:
int[,] myArr = { {1, 2}, {3, 4} }; dynamic myObj = new ExpandoObject(); var intItems = new List<dynamic>(); foreach(var myInt in myArr) { intItems.Add(new { value = myInt, value_plus_1 = myInt + 1 }); } myObj.Ints = intItems.ToArray(); // 也可以直接用List,根据需求选择
方案二:循环中动态扩展集合
如果你想在循环内直接操作myObj.Ints,可以先判断它是否已存在,不存在就初始化,存在则追加元素:
int[,] myArr = { {1, 2}, {3, 4} }; dynamic myObj = new ExpandoObject(); // ExpandoObject本质是字典,强转后方便操作 var expandoDict = (IDictionary<string, object>)myObj; foreach(var myInt in myArr) { var newItem = new { value = myInt, value_plus_1 = myInt + 1 }; if (expandoDict.ContainsKey("Ints")) { // 将现有数组转为列表,添加新元素后再转回数组 var existingItems = ((IEnumerable<dynamic>)expandoDict["Ints"]).ToList(); existingItems.Add(newItem); expandoDict["Ints"] = existingItems.ToArray(); } else { // 第一次初始化集合 expandoDict["Ints"] = new[] { newItem }; } }
方案三:用LINQ一键生成(最简洁)
借助LINQ可以扁平化二维数组并直接投影成目标对象,代码更简洁:
int[,] myArr = { {1, 2}, {3, 4} }; dynamic myObj = new ExpandoObject(); // 先扁平化二维数组,再生成每个元素对应的对象 myObj.Ints = myArr.Cast<int>().Select(i => new { value = i, value_plus_1 = i + 1 }).ToArray();
为什么原代码会覆盖?
因为每次循环里的myObj.Ints = new[] { ... }都会创建一个仅包含当前元素的新数组,完全替换掉之前Ints的引用,所以最后只剩下最后一次循环创建的数组啦。
内容的提问来源于stack exchange,提问作者MTS
相关产品推荐
相关产品推荐

