Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/271.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 协调两个对象集合_C#_Collections - Fatal编程技术网

C# 协调两个对象集合

C# 协调两个对象集合,c#,collections,C#,Collections,我有一个表单,用户可以使用DataGrid修改对象集合。打开表单时,我创建原始集合的深度副本,如果按下“取消”按钮,我将丢弃该副本 问题是,当按下OK(确定)按钮时,我必须协调更改,可能是: 现有对象的修改属性 添加到集合中任何位置的新对象。 已删除现有对象。 现有对象已重新排序。 因为我需要保留原始引用,所以我不能只清除集合并添加修改的项 你知道一个简单的算法可以同步两个这样的集合吗 我使用的是C 3.5,所以LINQ是可用的。为什么不保留原始版本的副本,并绑定到实际的集合。如果绑定到实际集合

我有一个表单,用户可以使用DataGrid修改对象集合。打开表单时,我创建原始集合的深度副本,如果按下“取消”按钮,我将丢弃该副本

问题是,当按下OK(确定)按钮时,我必须协调更改,可能是:

现有对象的修改属性 添加到集合中任何位置的新对象。 已删除现有对象。 现有对象已重新排序。 因为我需要保留原始引用,所以我不能只清除集合并添加修改的项

你知道一个简单的算法可以同步两个这样的集合吗


我使用的是C 3.5,所以LINQ是可用的。

为什么不保留原始版本的副本,并绑定到实际的集合。如果绑定到实际集合,则不存在对账。按“取消”时,只需将实际收藏替换为原始收藏的副本即可。它基本上与您正在尝试的操作相反……但它应该更易于管理。

我处理这一问题的方式取决于具有唯一ID的对象集合。我也会传入存储库来处理这一问题,但为简洁起见,我省略了它。这与以下内容类似:

public static void MergeFields(IEnumerable<TYPE1> persistedValues, IEnumerable<TYPE1> newValues)
{
    var leftIds = persistedValues.Select(x => x.Id).ToArray();
    var rightIds = newValues.Select(x => x.Id).ToArray();

    var toUpdate = rightIds.Intersect(leftIds).ToArray();
    var toAdd = rightIds.Except(leftIds).ToArray();
    var toDelete = leftIds.Except(rightIds).ToArray();

    foreach(var id in toUpdate){
        var leftScope = persistedValues.Single(x => x.ID == id);
        var rightScope = newValues.Single(x => x.ID == id);

        // Map appropriate values from rightScope over to leftScope
    }

    foreach(var id in toAdd) {
        var rightScope = newValues.Single(x => x.ID == id);
        // Add rightScope to the repository
    }

    foreach(var id in toDelete) {
        var leftScope = persistedValues.Single(x => x.ID == id);
        // Remove leftScope from the repository
    }

    // persist the repository
}

我刚刚为我正在进行的一个项目制定了以下算法,我认为它符合您的要求。它遵循以下步骤:

创建原始列表的浅表副本。 清除原始列表。 Foreach是修改列表中的每个项目。 如果找到原始对象,则将其添加到列表中并更新其属性。 如果不是,就把它添加到列表中。 此方法维护新的顺序并重用原始引用,但要求对象具有唯一标识符。我用的是Guid

var originalPersons = m_originalList.ToList();
m_originalList.Clear();
foreach (var modifiedPerson in m_modifiedList)
{
    var originalPerson = originalPersons.FirstOrDefault(c => c.ID == modifiedPerson.ID);
    if (originalPerson == null)
        m_originalList.Add(modifiedPerson);
    else
    {
        m_originalList.Add(originalPerson);
        originalPerson.Document = modifiedPerson.Document;
        originalPerson.Name = modifiedPerson.Name;
        ...
    }
}

祝你好运。

这其实是同一个问题。在取消时,我必须进行相同的对账,因为对象可能已被删除或重新排序。在取消时,您希望将集合恢复到进行任何编辑之前的状态。通过在绑定到集合之前复制集合,可以获得原始状态。您只需清除绑定的集合,并用副本的内容填充它。取消并不意味着删除和重新排序被禁止,而添加和编辑被放弃。取消意味着将集合恢复到以前的状态。取消时不需要对账。但对象的属性也将被修改。我可能不清楚,但您正在复制列表。这将创建整个事物的完整副本,包括对象。我认为很明显,如果你只是简单的克隆,它是不会工作的。我不知道如何解释它,但他的解决方案非常简单,应该可以大大减少您的工作量。它会消耗内存,但除非您绑定到一个百万项目列表,否则这不太可能是一个问题。如果我制作了一个列表的深度副本,我会丢失应该保持不变的原始引用。