0

我有一个无法迭代的集合(通过索引),但它确实实现了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是通过枚举器。类型中没有AddorAddAt方法(此处由 . 扮演object[]。假设底层结构未知/高度复杂。

我怎样才能做到这一点?

4

4 回答 4

1

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

枚举集合时,您只能尝试更改正在枚举的数据。你绝对不能删除任何东西。这部分是由于改变枚举的潜力。

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

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

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

于 2012-06-05T18:51:02.403 回答
0

你描述它的方式,我想不出可以轻松更换物品。
您声称:

  • 没有添加/删除方法 - 没有简单的更改方法
  • 底层集合的格式未知 - 使反射选项更难使用
  • 你只有枚举器暴露给你——这意味着你只能 foreach

可能的解决方案是:

  • 反映底层类型,学习它的格式并通过反射来改变你想要的任何东西
  • 如果可能的话,使用深拷贝,正如我已经建议的那样。深拷贝,如果您不熟悉该术语,意味着您将在递归中更新要替换的对象及其属性,根据需要使用您要放置的对象的并行值而不是被替换的对象. 当然,如果您关心引用而不关心每个对象的数据/值,则此解决方案将不起作用。有几十个线程解释了如何在 SO 上使用深拷贝,所以找到一个样本应该没有问题
于 2012-06-05T19:19:15.697 回答
0

一句话:链表

您还没有说是否需要实现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++;
    }
}
于 2012-06-05T19:15:40.113 回答
0

原始集合有哪些变异方法?如果它支持删除或替换项目,它通过什么方式识别要删除或替换的项目?

一些实现IEnumerableIEnumerable<T>将允许枚举工作的类即使在修改了基础集合时也能正常工作(在整个枚举中都在集合中的项目将完全返回,在枚举的一部分集合中的项目将最多返回一次,而那些在枚举过程中根本不是集合的将根本不返回)。如果您正在使用的类的行为方式如此,那就太好了。

否则,您最好的选择可能是在枚举类时构建“编辑”列表,然后在枚举完成后应用这些编辑。

于 2012-06-05T21:15:30.253 回答