How can I add an item to a IEnumerable<T> collection?

How can I add an item to a IEnumerable<T> collection?

My question as title above. For example

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

but after all it only has 1 item inside. Can we have a method like items.Add(item) like the List<T>?

 

评论

IEnumerable<T> is meant for querying collections only. It is the backbone for the LINQ framework. It is always an abstraction of some other collection such as Collection<T>, List<T>, or Array. The interface only provides a GetEnumerator method that returns an instance of IEnumerator<T> that enables the walking of the extending collection one item at a time. The LINQ extension methods are limited by this interface. IEnumerable<T> is designed to be read only because it may represent an aggregation of parts of multiple collections.
– Jordan
Jan 27, 2016 at 16:04
 
 

回答1

You cannot, because IEnumerable<T> does not necessarily represent a collection to which items can be added. In fact, it does not necessarily represent a collection at all! For example:

IEnumerable<string> ReadLines()
{
     string s;
     do
     {
          s = Console.ReadLine();
          yield return s;
     } while (!string.IsNullOrEmpty(s));
}

IEnumerable<string> lines = ReadLines();
lines.Add("foo") // so what is this supposed to do??

What you can do, however, is create a new IEnumerable object (of unspecified type), which, when enumerated, will provide all items of the old one, plus some of your own. You use Enumerable.Concat for that:

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

This will not change the array object (you cannot insert items into to arrays, anyway). But it will create a new object that will list all items in the array, and then "Foo". Furthermore, that new object will keep track of changes in the array (i.e. whenever you enumerate it, you'll see the current values of items).

 

回答2

The type IEnumerable<T> does not support such operations. The purpose of the IEnumerable<T> interface is to allow a consumer to view the contents of a collection. Not to modify the values.

When you do operations like .ToList().Add() you are creating a new List<T> and adding a value to that list. It has no connection to the original list.

What you can do is use the Add extension method to create a new IEnumerable<T> with the added value.

items = items.Add("msg2");

Even in this case it won't modify the original IEnumerable<T> object. This can be verified by holding a reference to it. For example

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

After this set of operations the variable temp will still only reference an enumerable with a single element "foo" in the set of values while items will reference a different enumerable with values "foo" and "bar".

EDIT

I contstantly forget that Add is not a typical extension method on IEnumerable<T> because it's one of the first ones that I end up defining. Here it is

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

 

回答3

Have you considered using ICollection<T> or IList<T> interfaces instead, they exist for the very reason that you want to have an Add method on an IEnumerable<T>.

IEnumerable<T> is used to 'mark' a type as being...well, enumerable or just a sequence of items without necessarily making any guarantees of whether the real underlying object supports adding/removing of items. Also remember that these interfaces implement IEnumerable<T> so you get all the extensions methods that you get with IEnumerable<T> as well.

 

回答4

In .net Core, there is a method Enumerable.Append that does exactly that.

The source code of the method is available on GitHub..... The implementation (more sophisticated than the suggestions in other answers) is worth a look :).

 

This is not only in core, also the framework 4.7.1 and newer: docs.microsoft.com/en-us/dotnet/api/…
– sschoof
May 21, 2019 at 14:23
 

 

作者:Chuck Lu    GitHub    
posted @   ChuckLu  阅读(468)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 全程不用写代码,我用AI程序员写了一个飞机大战
· DeepSeek 开源周回顾「GitHub 热点速览」
· MongoDB 8.0这个新功能碉堡了,比商业数据库还牛
· 记一次.NET内存居高不下排查解决与启示
· 白话解读 Dapr 1.15:你的「微服务管家」又秀新绝活了
历史上的今天:
2021-09-08 OpenSSL errno 10054
2021-09-08 Why aren't telnet bots finishing the three-way handshake?
2021-09-08 Telnet shows blank screen on port 443 but TCP handshake not done 【openssl s_client -connect】
2021-09-08 You have a private key that corresponds to this certificate but CryptAcquireCertificatePrivateKey failed.
2021-09-08 劳动合同的必备条款有哪些?
2021-09-08 openssl pkcs12
2021-09-08 How to generate a self-signed SSL certificate using OpenSSL?
点击右上角即可分享
微信分享提示