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

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/1210295/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-06 11:00:12  来源:igfitidea点击:

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

c#listienumerable

提问by ldsenow

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.

但毕竟里面只有 1 个项目。

Can we have a method like items.Add(item)?

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

like the List<T>

List<T>

采纳答案by Pavel Minaev

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<T>不一定代表可以添加项目的集合。事实上,它并不一定代表一个集合!例如:

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 newIEnumerableobject (of unspecified type), which, when enumerated, will provide all items of the old one, plus some of your own. You use Enumerable.Concatfor that:

但是,您可以做的是创建一个IEnumerable对象(未指定类型),当枚举该对象时,将提供旧对象的所有项目,以及您自己的一些项目。你使用Enumerable.Concat

 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).

不会更改数组对象(无论如何,您不能将项目插入到数组中)。但它会创建一个新对象,列出数组中的所有项目,然后是“Foo”。此外,该新对象将跟踪数组中的更改(即,无论何时枚举它,您都会看到项目的当前值)。

回答by Paul van Brenk

No the IEnumerable doesn't support adding items to it.

不,IEnumerable 不支持向其中添加项目。

You 'alternative' is:

你的“替代”是:

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

回答by JaredPar

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.

该类型IEnumerable<T>不支持此类操作。该IEnumerable<T>接口的目的是允许消费者查看集合的内容。不修改值。

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.

当您执行 .ToList().Add() 之类的操作时,您正在创建一个新的List<T>并向该列表添加一个值。它与原始列表没有联系。

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

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

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

即使在这种情况下,它也不会修改原始IEnumerable<T>对象。这可以通过持有对它的引用来验证。例如

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".

在这组操作之后,变量 temp 仍将仅引用值集中具有单个元素“foo”的枚举,而项目将引用具有值“foo”和“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

我总是忘记 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;
}

回答by Sam Harwell

Not only can you not add items like you state, but if you add an item to a List<T>(or pretty much any other non-read only collection) that you have an existing enumerator for, the enumerator is invalidated (throws InvalidOperationExceptionfrom then on).

您不仅不能像您List<T>所说的那样添加项目,而且如果您将一个项目添加到您拥有现有枚举器的(或几乎任何其他非只读集合)中,则该枚举器将失效(InvalidOperationException从那时起抛出)。

If you are aggregating results from some type of data query, you can use the Concatextension method:

如果您正在聚合某种类型的数据查询的结果,您可以使用Concat扩展方法:

Edit: I originally used the Unionextension in the example, which is not really correct. My application uses it extensively to make sure overlapping queries don't duplicate results.

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

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

回答by jason

Others have already given great explanations regarding why you can not (and should not!) be able to add items to an IEnumerable. I will only add that if you are looking to continue coding to an interface that represents a collection and want an add method, you should code to ICollectionor IList. As an added bonanza, these interfaces implement IEnumerable.

其他人已经给出了关于为什么不能(也不应该!)能够将项目添加到IEnumerable. 我只会补充一点,如果您希望继续对表示集合的接口进行编码并想要一个 add 方法,您应该编码为ICollectionIList。作为额外的财富,这些接口实现了IEnumerable.

回答by Abhijeet Patel

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

您是否考虑过使用ICollection<T>IList<T>接口,它们的存在正是因为您希望AddIEnumerable<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.

IEnumerable<T>用于将类型“标记”为......好吧,可枚举或只是一个项目序列,而不必保证真正的底层对象是否支持添加/删除项目。还请记住,这些接口实现了,IEnumerable<T>因此您也可以获得所有扩展方法IEnumerable<T>

回答by Abhijeet Patel

A couple short, sweet extension methods on IEnumerableand IEnumerable<T>do it for me:

几个简短的,甜蜜的扩展方法,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);
}

Elegant (well, except for the non-generic versions). Too bad these methods are not in the BCL.

优雅(嗯,除了非通用版本)。可惜这些方法不在 BCL 中。

回答by Lrodriguez84

you can do this.

你可以这样做。

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

回答by Juha Sinkkonen

Easyest way to do that is simply

最简单的方法就是

IEnumerable<T> items = new T[]{new T("msg")};
List<string> itemsList = new List<string>();
itemsList.AddRange(items.Select(y => y.ToString()));
itemsList.Add("msg2");

Then you can return list as IEnumerable also because it implements IEnumerable interface

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

回答by Aamol

To add second message you need to -

要添加第二条消息,您需要 -

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