如何将项目添加到IEnumerable <T>集合?

我的问题如上所述。 例如,

IEnumerable<T> items = new T[]{new T("msg")}; items.ToList().Add(new T("msg2")); 

但毕竟它里面只有一件东西。

我们可以有一个方法像items.Add(item)

List<T>

您不能,因为IEnumerable<T>不一定代表可添加项目的集合。 事实上,它并不一定代表一个集合! 例如:

 IEnumerable<string> ReadLines() { string s; do { s = Console.ReadLine(); yield return s; } while (s != ""); } IEnumerable<string> lines = ReadLines(); lines.Add("foo") // so what is this supposed to do?? 

但是,您可以做的是创build一个新的 IEnumerable对象(未指定types),枚举时将提供所有旧项目以及您自己的项目。 您使用Enumerable.Concat为:

  items = items.Concat(new[] { "foo" }); 

不会改变数组对象 (无论如何你都不能将项目插入到数组中)。 但它会创build一个新的对象,列出数组中的所有项目,然后是“Foo”。 而且,这个新的对象将跟踪数组中的变化 (例如,每当你枚举它,你会看到项目的当前值)。

IEnumerable<T>types不支持这种操作。 IEnumerable<T>接口的目的是让消费者查看集合的内容。 不要修改这些值。

当您执行像.ToList()。Add()这样的操作时,您正在创build一个新的List<T>并将值添加到该列表中。 它与原始列表没有关系。

您可以使用Add扩展方法创build一个新的具有附加值的IEnumerable<T>

 items = items.Add("msg2"); 

即使在这种情况下,它也不会修改原始的IEnumerable<T>对象。 这可以通过参考来validation。 例如

 var items = new string[]{"foo"}; var temp = items; items = items.Add("bar"); 

在这组操作之后,variablestemp将仍然只引用具有值集合中的单个元素“foo”的枚举,而项目将引用具有值“foo”和“bar”的不同枚举。

编辑

我不断地忘记,Add不是IEnumerable<T>的典型扩展方法,因为它是我最终定义的第一个扩展方法之一。 这里是

 public static IEnumerable<T> Add<T>(this IEnumerable<T> e, T value) { foreach ( var cur in e) { yield return cur; } yield return value; } 

你有没有考虑使用ICollection <T>或IList <T>接口,它们存在的原因是你想在IEnumerable <T>上有一个'Add'方法。 IEnumerable <T>用于将types标记为…以及可枚举或只是一系列的项目,而不必确保真实的底层对象是否支持添加/删除项目。 还要记住,这些接口实现IEnumerable <T>,所以你可以获得IEnumerable <T>获得的所有扩展方法。

对于IEnumerableIEnumerable<T>来说,两个简短而可爱的扩展方法对我来说是这样的:

 public static IEnumerable Append(this IEnumerable first, params object[] second) { return first.OfType<object>().Concat(second); } public static IEnumerable<T> Append<T>(this IEnumerable<T> first, params T[] second) { return first.Concat(second); } public static IEnumerable Prepend(this IEnumerable first, params object[] second) { return second.Concat(first.OfType<object>()); } public static IEnumerable<T> Prepend<T>(this IEnumerable<T> first, params T[] second) { return second.Concat(first); } 

优雅(除非非通用版本)。 太糟糕了,这些方法不在BCL中。

IEnumerable不支持添加项目。

一个'替代'你有。

 var List = new List(items); List.Add(otherItem); 

你不仅可以添加像你陈述的项目,但是如果你添加一个项目到一个List<T> (或几乎任何其他非只读集合),你有一个现有的枚举器,枚举器是无效的(抛出InvalidOperationException从那时起)。

如果您正在汇总某种types的数据查询的结果,则可以使用Concat扩展方法:

编辑:我原来在例子中使用了Union扩展,这是不正确的。 我的应用程序广泛使用它来确保重叠查询不会重复结果。

 IEnumerable<T> itemsA = ...; IEnumerable<T> itemsB = ...; IEnumerable<T> itemsC = ...; return itemsA.Concat(itemsB).Concat(itemsC); 

要添加第二条消息,你需要 –

 IEnumerable<T> items = new T[]{new T("msg")}; items = items.Concat(new[] {new T("msg2")}) 

其他人已经给出了很好的解释,为什么你不能(不应该)能够添加项目到IEnumerable 。 我只会补充一点,如果你想继续编码到代表一个集合的接口,并且想要一个add方法,你应该编码到ICollection或者IList 。 作为一个附加的富矿,这些接口实现IEnumerable

你可以这样做。

 //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; 

我只是来这里说,除了Enumerable.Concat扩展方法外,在.NET Core 1.1.1中似乎还有一个名为Enumerable.Append方法。 后者允许您将单个项目连接到现有序列。 所以阿莫尔的回答也可以写成

 IEnumerable<T> items = new T[]{new T("msg")}; items = items.Append(new T("msg2")); 

不过,请注意,这个函数不会改变input序列,它只是返回一个包装,将给定的序列和附加的项目放在一起。

在.net核心中,有一个方法Enumerable.Append正是那样做的。

该方法的源代码在GitHub上可用。 ….实现(比其他答案中的build议更复杂)值得一看:)。

最简单的方法是简单的

 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接口

当然,你可以(我将你的电子商务放在一边):

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