如何向IEnumerable<T>中添加一个元素最佳方法是什么?

33

以下是我如何向IEnumerable对象添加一个项:

//Some IEnumerable<T> object
IEnumerable<string> arr = new string[] { "ABC", "DEF", "GHI" };

//Add one item
arr = arr.Concat(new string[] { "JKL" });

这有点尴尬。我没有看到类似于ConcatSingle()的方法。

是否有更简洁的方法将单个项目添加到IEnumerable对象中?


@Chris:我已经回滚了。SO之前移除那个功能是有原因的。 - Daniel Hilgarth
没有意识到该功能已经被添加了。谢谢纠正。 - Chris Ballance
6个回答

23

不,使用内置语言/框架功能这就是最简洁的了。

如果你愿意,你可以创建一个扩展方法:

arr = arr.Append("JKL");
// or
arr = arr.Append("123", "456");
// or
arr = arr.Append("MNO", "PQR", "STU", "VWY", "etc", "...");

// ...

public static class EnumerableExtensions
{
    public static IEnumerable<T> Append<T>(
        this IEnumerable<T> source, params T[] tail)
    {
        return source.Concat(tail);
    }
}

System.Linq 命名空间中有这样的方法。 - Piotr Nawrot

9

IEnumerable 是一种不可变集合,这意味着您不能添加或删除元素。相反,您必须创建一个新的集合来进行操作,最简单的方法是将其转换为列表再进行添加:

var newCollection = arr.ToList();
newCollection.Add("JKL"); //is your new collection with the item added

也许我漏掉了什么......但是Add方法不会返回新列表....https://msdn.microsoft.com/zh-cn/library/vstudio/3wcytfd1(v=vs.100).aspx - Joshua Enfield
“Add”不会返回新列表,但因为“List”是可变集合,您可以简单地引用“List”对象以访问“新列表”。从这个意义上说,这个答案有点学究(因为很明显OP是在问如何从另一个IEnumerable和一个附加对象创建一个新的IEnumerable)。 - Kenny Evitt
IEnumerable是一个不可变的集合--这是错误的,它不是一个集合,而是一个接口。实现它的类的对象可以是不可变的(例如Array)或可变的(例如List<T>),这取决于实现方式。 - tsul

8

请编写一个扩展方法ConcatSingle :)

public static IEnumerable<T> ConcatSingle<T>(this IEnumerable<T> source, T item)
{
    return source.Concat(new [] { item } );
}

但是您需要更加小心使用术语。
您不能向 IEnumerable<T> 添加项目。Concat 会创建一个新实例。

示例:

var items = Enumerable.Range<int>(1, 10)
Console.WriteLine(items.Count()); // 10
var original= items;
items = items.ConcatSingle(11);
Console.WriteLine(original.Count());   // 10
Console.WriteLine(items.Count()); // 11

正如您所看到的,原始枚举 - 我们保存在 original 中的枚举并没有改变。


7

由于 IEnumerable 是只读的,你需要转换成列表。

var new_one = arr.ToList().Add("JKL");

或者您可以获取像这样的扩展方法;

public static IEnumerable<T> Append<T>(this IEnumerable<T> source, params T[] item)
{
    return source.Concat(item);
}

1
IEnumerable<T> 是只读的。这并不意味着它是不可变的。不可变集合是永远不会改变的集合。IEnumerable<T> 甚至不能保证引用不能被强制转换为可变类型,更不能保证底层集合不会改变。 - supercat

3

有趣,谢谢。看起来新的.Net版本正在将链接列表附加到给定IEnumerable的开头和结尾。 - user2023861

2

你正在将一个数组赋值给IEnumerable。为什么不使用Array类型代替IEnumerable呢?

否则,如果你想更改集合,可以使用IList(或List)。

当我需要读取时,我只使用IEnumerable作为方法参数,而当我需要更改其中的项时,则使用IList(或List)。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接