代码之家  ›  专栏  ›  技术社区  ›  Vivian River

向IEnumerable集合添加单个元素的最佳方法是什么?

  •  11
  • Vivian River  · 技术社区  · 14 年前

    我很惊讶地发现,似乎没有一个方法可以向IEnumerable集合添加单个元素。

    如何向IEnumerable集合添加单个元素?

    8 回复  |  直到 14 年前
        1
  •  24
  •   jonnii    14 年前

    不能向IEnumerable添加元素,因为它应该是只读的。你最好的选择是:

    return new List<Foo>(enumerable){ new Foo() };
    

    return enumerable.Concat(new [] { new Foo() });
    
        2
  •  20
  •   nawfal Donny V.    12 年前

    IEnumerable的要点是它是一个只读的pull样式集合。如果需要,可以通过执行以下操作来模拟添加:

    public static IEnumerable<T> Add<T>(this IEnumerable<T> source, T additionalItem)
    {
       foreach(var item in source)
       {
          yield return item;
       }
    
       yield return additionalItem;
    }
    
        3
  •  7
  •   Leigh S    14 年前

    我想指出这里的其他一些答案:IEnumerable不是只读集合,它根本不是集合。它是一个接口,定义如何遍历集合。

    如果要添加对象,则应将对象添加到具体的集合类中,或者至少使用其他接口。

        4
  •  6
  •   R. Martinho Fernandes    14 年前

    您可以将它与单例数组连接起来:

    IEnumerable xs;
    xs.Concat(new[]{x});
    
        5
  •  4
  •   Community CDub    8 年前

    记住其他人所说的不能真正“添加”到可枚举的,您仍然可以模拟添加。事实上,我认为您可以通过将序列变形为一个实际上“包含”该项的新序列来“添加”该项到序列中(如果您不相信我,只需遍历新序列!).

    您还可以将单个项表示为可枚举项,如下所示:

    //ToEnumerable might not be the best name here
    public static IEnumerable<T> ToEnumerable<T>(this T item)
    {
        return Enumerable.Repeat(item,1);
    }
    

    public static IEnumerable<T> ToEnumerable<T>(this T item)
    {
        yield return item;
    }
    

    然后,您可以将一个项“添加”到可枚举项,如下所示:

    var items = GetSomeItems();
    
    var itemsWithNewItemOnEnd = items.Concat(somenewitem.ToEnumerable());
    
    var itemsWithNewItemAtStart = somenewitem.ToEnumerable().Concat(items);
    

    您甚至可以按如下顺序将项目插入到其他位置(假设您知道要插入项目的位置):

    var itemsWithNewItemInserted = items.Take(5).Concat(somenewitem.ToEnumerable()).Concat(items.Skip(5));
    

    操作完成后(即操作序列使其“包含”要包含的内容),您可能希望通过ToArray或ToList方法在序列中创建数组或列表:

    var itemsWithNewItemInserted = items.Take(5).Concat(somenewitem.ToEnumerable()).Concat(items.Skip(5)).ToList();
    

    现在,使用NeWITIMAN插入的是一个包含原始列表中所有期望项目的列表,其中新项目插入中间。

    由于每个添加的扩展方法(Take、Skip等)都可能导致序列被多次迭代,因此,在这样的序列上游手好闲(Take、Skip、inserting等)可能会花费您一段时间,但是列表理解语法确实使使用常规迭代。

    此外,下面还有一些链接讨论如何将单个项表示为IEnumerable:

    Passing a single item as IEnumerable<T>

    Is there a neater linq way to 'Union' a single item?

        6
  •  2
  •   Andy Lowry    14 年前

    IEnumerable是只读集合,ICollection提供了一个带有Add和Remove的可变集合。

    但是,您可以创建一个新的IEnumerable,它包含原始IEnumerable中的所有项和一个新项,方法是连接两个列表:

    var newCollection = original.Concat(new[]{element});
    
        7
  •  0
  •   Bryan    14 年前

    IEnumerable 设计用于在项上迭代。它并不总是以收藏为后盾。此外,在循环访问集合时,不能修改该集合。

    如果在遍历集合时需要更新集合,则需要在启动 foreach 循环。林肯的 ToList() 方法是一个很好的方法。

        8
  •  0
  •   Brosto    14 年前

    可能不是您要寻找的答案,但使用泛型集合类似乎总能为我解决此类问题。他们中的大多数人都有一个.Add(T)方法。

    推荐文章