【问题标题】:Items added to List (AddRange) are changed when the table added to AddRange is changed当添加到 AddRange 的表发生更改时,添加到 List (AddRange) 的项目会更改
【发布时间】:2019-01-28 23:11:55
【问题描述】:

如果我在循环之外启动我的临时列表,我希望会发生这种情况,但我不是那么不明白为什么我会得到我的结果。我的代码本质上是:

foreach (DataRow dtRow in dt.Rows)
{
    List<IItemData> tempTable = new List<IItemData>();
    tempTable = CreateCopyOfTemplate(item, new List<IItemData>(), tableTemplate, itemDataList, item.Id, tableSortOrder);

    foreach (IItemData itemData in tempTable)
    {
        if (itemData.Content.StartsWith("cdt:") && itemData.DataSource.Description == nameof(DataSource.CustomDataTableValue))
        {
            itemData.Content = dtRow[itemData.Content.Replace("cdt:", "")].ToString();
        }
    }

    tableSortOrder++;
    itemDataList.AddRange(tempTable.ToList());
}


private static List<IItemData> CreateCopyOfTemplate(IItemData itemData, List<IItemData> newTable, List<IItemData> templateTable, List<IItemData> originalTable, int? origParentId, int tableSortOrder)
{
    List<IItemData> childList = templateTable.Where(x => x.ParentId == origParentId).ToList();

    if (itemData.DataSource != null && itemData.DataSource.Description == nameof(DataSource.CustomDataTable))
    {
        itemData.Id = originalTable.Max(x => x.Id) + 1;
        itemData.SortOrder = tableSortOrder;
        newTable.Add(itemData);
    }

    foreach (IItemData childItem in childList)
    {
        origParentId = childItem.Id;
        childItem.ParentId = itemData.Id;
        childItem.Id = newTable.Max(x => x.Id) + 1;
        newTable.Add(childItem);

        CreateCopyOfTemplate(childItem, newTable, templateTable, originalTable, origParentId, tableSortOrder);
    }

    return newTable;
}

在 ForEach 循环的每次传递中,我都会创建一个名为 tempTable 的新 List&lt;IITemData&gt;。我用一个方法填充它,然后添加一些其他位,然后将其添加到另一个名为 itemDataList 的列表的范围中。

我首先在循环中启动了 tempTable 列表,并且在应用到主列表时也使用了 ToList() 但是在循环的第一遍添加的记录全部更新为第二遍的值循环 - 因此在我的列表中出现重复数据!

我感觉我遗漏了一些明显的东西,但这是漫长的一天,我无法弄清楚。

【问题讨论】:

  • 我认为您没有向我们展示足够的代码来确定实际问题是什么。阅读stackoverflow.com/help/mcve
  • 我已经更新了我的完整代码...任何建议将不胜感激!

标签: c# list foreach reference


【解决方案1】:

所以我不是 100% 确定,但看起来您在 foreach 循环的每个通道中重用“项目”对象,您在 CreateCopyOfTemplate 中对其进行了一些更改,然后将其添加到 newTable 并返回它.只是再次传递它,进行一些更改并返回它。最终使用相同的参考

if (itemData.DataSource != null && itemData.DataSource.Description == nameof(DataSource.CustomDataTable))
{

    itemData.Id = originalTable.Max(x => x.Id) + 1;
    itemData.SortOrder = tableSortOrder;
    newTable.Add(itemData); <-- Here you keep adding the same item
}

您可以实例化一个实现 IItemData 的对象的新实例并使用它来代替。一种简单的方法可能是在那里深度复制对象,或者只是手动设置所有属性。

看这里: https://docs.microsoft.com/en-us/dotnet/api/system.object.memberwiseclone?view=netframework-4.7.2

【讨论】:

  • 我愚蠢地认为通过执行 ToList() 会创建一个未引用原始 tempTable 列表的新实例......不是这样吗?如果没有,那么如何在没有参考的情况下应用 tempTable 列表?
  • 确实如此,但在代码中的某处(我想在 MethodToReturnListItems 中)它导致它使用引用代替。
  • 啊,好吧,我还在学习其中的一些细节,但不知道那是一回事。我会用完整的代码更新...我希望上面的小 sn-p 就足够了,但显然不是。
  • 所以我不是 100% 确定,但看起来你在 foreach 循环的每次传递中重用了“item”对象,你在 CreateCopyOfTemplate 中对其进行了一些更改,然后添加 i到 newTable 并返回它。只是再次传递它,进行一些更改并返回它。最终使用相同的参考
  • 完成,谢谢。让我重回正轨!
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2019-06-08
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多