更改可枚举集合中的对象

本文关键字:对象 集合 枚举 | 更新日期: 2023-09-27 18:36:16

我有一个无法迭代的集合(通过索引),但它确实实现了IEnumerable

有没有办法在枚举时替换该集合中的对象?我知道这在foreach循环中是不可能的,但这似乎是一件合理的事情。

我甚至考虑使用 C# 的指针,但这些指针不适用于托管类型。

我知道我可以用所有数据填充数组,然后以这种方式对其进行编辑,但是

  1. 这似乎很浪费
  2. 更重要的是,它失去了整个结构。

例如:

public void Example(object a,object b, object c)
{
    object[] ex = {a,b,c};
    object d = new MyCustomType();
}

在不使用任何索引器的情况下,如何使ex保存{a,d,c}?假设我可以访问ex的唯一方法是通过枚举器。类型中没有AddAddAt方法(此处由object[]播放。假设底层结构未知/高度复杂。

我该怎么做?

更改可枚举集合中的对象

正如帕约所说,您的陈述相互冲突。 您无法遍历 IEnumerable,但您处于 foreach 循环中,即迭代。 IEnumerable几乎说你可以通过集合枚举。 但这是我对你的问题的意见:

通过集合进行枚举时,更改要枚举的数据的任何尝试都会受到限制。 而且您绝对不能删除任何内容。 部分原因是由于更改枚举的可能性。

一种可能的方法是创建一个项目列表,枚举列表并将所需的内容放入列表中。 然后重新加载 IEnumerable,假设它们公开 .添加(IE可枚举列表)。

在一种情况下,我有想要从 IEnumerable 中删除的项目,所以我做了一个 foreach,跟踪我要删除的每个对象,然后在枚举后,我对我保存的每个对象进行了删除。

如今,使用 linq,您可以更轻松地执行删除对象之类的操作,如果您可以对您想要的内容进行很好的定义查询(省略您不想要的内容),然后针对 IQueriable 结果集进行处理。

你描述它的方式,我想不出轻松替换项目的方法。
您声称:

  • 没有添加/删除方法 - 没有简单的更改方法
  • 基础集合的格式未被选中 - 使反射选项更难使用
  • 您只有枚举器暴露给您 - 这意味着您只能针对每个

可能的解决方案是:

  • 反映基础类型,了解其格式并通过反射更改所需的任何内容
  • 如果可能的话,按照我已经建议的那样使用深拷贝。如果您不熟悉该术语,则深拷贝意味着您将根据需要更新要替换的对象及其属性,并根据需要使用要放置的对象中的并行值而不是替换的对象中的并行值进行更新。当然,如果您关心引用而不是每个对象的数据/值,则此解决方案将不起作用。有几十个线程解释了如何在SO上使用深度复制,因此查找样本应该没有问题

一句话:链表

您尚未说明是否需要实现IEnumerable例如用于 LINQ),或者您对所引用的神秘集合有多少控制权。但是,如果您的问题基本上是"如何在 C# 中循环访问某种集合时修改它?...嗯,这就是链表实际上擅长(并且非常有效)的地方。例如:

var intList = new LinkedList<int>(new []{ 1, 4, 5, 7, 12 });
var node = intList.First;
do {
    // do stuff with node
    if (node.Value < 3){
        node.List.AddAfter(node, node.Value + 1);
    } else if(node.Value == 7) {
        var prevNode = node.Previous;
        node.List.Remove(node);
        node = prevNode;
    }
    // Get the next node
    node = node.Next;
} while (node != null);

我并不是说你应该将你的来源收集复制到链表中,因为我们没有足够的信息来自你。但也许这可以向你和未来的读者展示链表的用途——即在没有索引访问器的情况下进行枚举时进行修改。

请注意,如果您引用的这个集合完全是假设的,那么您提供的信息没有答案:IEnumerable不需要任何方法来修改"底层集合"。事实上,IEnumerable甚至不需要有一个底层集合。例如,下面是返回没有基础集合的IEnumerable<int>的方法:

public static IEnumerable<int> Range(int minValue, int maxValue) {
    int current = minValue;
    while (current <= maxValue) {
        yield return current;
        current++;
    }
}

原始集合有哪些突变方法? 如果它支持移除或更换物品,它通过什么方式标识要移除或更换的物品?

一些实现 IEnumerableIEnumerable<T> 的类将允许枚举正常工作,即使修改了基础集合(在整个枚举过程中集合中的项将只返回 1 项,部分枚举在集合中的项最多返回一次,而在枚举期间根本不返回集合的项根本不返回)。 如果您使用的类以这种方式运行,那就太好了。

否则,最好的办法可能是在枚举类时生成"编辑"列表,然后在枚举完成后应用这些编辑。