如何向IEnumerable<T>集合中添加一个项目?

502
我的问题就是如上标题所述。例如:
IEnumerable<T> items = new T[]{new T("msg")};
items.ToList().Add(new T("msg2"));

但毕竟它只有一个项目。我们是否可以像List<T>那样拥有一个items.Add(item)的方法?与此类似。


6
IEnumerable<T> 仅用于查询集合,是 LINQ 框架的核心。它始终是其他集合类型(如 Collection<T>List<T>Array)的抽象表示。该接口只提供了一个 GetEnumerator 方法,返回一个 IEnumerator<T> 实例,使得能够一次迭代扩展集合中的一个项。由于该接口的限制,LINQ 扩展方法也受到了限制。IEnumerable<T> 被设计成只读的,因为它可能代表多个集合部分的聚合。 - Jordan
3
举个例子,只需声明IList<T>而不是IEnumerable<T>IList<T> items = new T[]{new T("msg")}; items.Add(new T("msg2")); - NightOwl888
17个回答

3

你可以做到这一点。

//Create IEnumerable    
IEnumerable<T> items = new T[]{new T("msg")};

//Convert to list.
List<T> list = items.ToList();

//Add new item to list.
list.add(new T("msg2"));

//Cast list to IEnumerable
items = (IEnumerable<T>)items;

9
这个问题在5年前已经有了一份更完整的回答。看看被采纳的答案,作为一个好答案的例子。 - pquest
1
最后一行是:items = (IEnumerable<T>)list; - Belen Martin

2

实现IEnumerable和IEnumerator接口的实例(从IEnumerable返回)没有任何API允许修改集合,该接口提供只读API。

实际上修改集合的两种方法:

  1. 如果实例恰好是具有写入API的某个集合(例如List),则可以尝试将其转换为此类型:

IList<string> list = enumerableInstance as IList<string>;

  1. 从IEnumerable创建列表(例如通过LINQ扩展方法toList()):

var list = enumerableInstance.toList();


1
最简单的方法就是简单地这样做。
IEnumerable<T> items = new T[]{new T("msg")};
List<string> itemsList = new List<string>();
itemsList.AddRange(items.Select(y => y.ToString()));
itemsList.Add("msg2");

然后你也可以将列表作为IEnumerable返回,因为它实现了IEnumerable接口。

1

Enumerable.Empty(T)会返回一个类型为T的空集合。

创建一个名为somevalues的List对象。

将someValues添加到items的列表中,可以使用items.ToList().Add(someValues)方法。如果要添加多个值,则可以使用items.ToList().AddRange(someValues)方法。


1
最好包括评论来解释你的答案,特别是考虑到有许多相关答案,以便解释您的不同之处。此外,请考虑将代码格式化为代码块。 - Denis G. Labrecque

-2
也许我来晚了,但我希望它能帮助未来的任何人。
您可以使用插入函数在特定索引处添加项目。 list.insert(0, item);

-2

非常抱歉翻出这个古老的问题,但由于它在谷歌搜索结果中排名靠前,我认为仍有人会来到这里。

在众多答案中,有些真正有价值且解释得很好,我想补充一个不同的观点,因为在我看来,问题还没有被很好地识别出来。

您正在声明一个存储数据的变量,您需要通过添加项目来更改它吗?那么您不应该将其声明为IEnumerable。

如@NightOwl888所提议的

对于这个示例,只需声明IList而不是IEnumerable:IList items = new T[] {new T("msg")}; items.Add(new T("msg2"));

试图绕过已声明的接口限制只会显示您做出了错误的选择。 除此之外,所有提出的方法都应该被忽略,因为它们实现了其他实现中已经存在的东西。 已经存在可以让您添加项目的类和接口。为什么总是要重新创建已经在其他地方完成的事情呢?

这种考虑是在接口内抽象变量功能的目标。

简而言之:在我看来,这些是实现您所需的最干净的方法:

// 1st choice : Changing declaration
IList<T> variable = new T[] { };
variable.Add(new T());

// 2nd choice : Changing instantiation, letting the framework taking care of declaration
var variable = new List<T> { };
variable.Add(new T());

当你需要将变量用作IEnumerable时,你可以这样做。当你需要将其用作数组时,你可以调用'ToArray()',它通常应该很简单。不需要扩展方法,仅在确实需要时进行转换,能够在变量上使用LinQ等……

停止因为声明/实例化时犯了一个错误而做奇怪和/或复杂的事情。


因为有很多现实情况下你无法控制正在处理的变量的类型,例如IEnumerable<T>是许多数据访问库函数的常见返回类型,所以被downvote了。这并没有回答问题,也没有令问题不再重要。 - topsail

-7

当然可以(我不考虑你的T业务):

public IEnumerable<string> tryAdd(IEnumerable<string> items)
{
    List<string> list = items.ToList();
    string obj = "";
    list.Add(obj);

    return list.Select(i => i);
}

我不知道为什么这个答案有8个踩,我认为这个解决方案可行而且不错。 - Mayer Spitz
使用concat方法会有更好的答案,而不是将其转换为列表,然后再转回IEnumerable。 这个解决方案可以工作,但性能不佳。 - Hulk

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