我的问题如上所述。例如

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

但毕竟里面只有一项。我们能不能有一个items.Add(item)方法,比如List<T>?


当前回答

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

当你执行像. tolist (). add()这样的操作时,你是在创建一个新的List<T>并向该列表添加一个值。它与原始列表没有关联。

您可以使用Add扩展方法使用添加的值创建一个新的IEnumerable<T>。

items = items.Add("msg2");

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

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

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

EDIT

我经常忘记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;
}

其他回答

不能,因为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??

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

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

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

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

如果您正在聚合来自某种类型的数据查询的结果,您可以使用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")};
List<string> itemsList = new List<string>();
itemsList.AddRange(items.Select(y => y.ToString()));
itemsList.Add("msg2");

然后你可以返回list作为IEnumerable,因为它实现了IEnumerable接口

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

实际上改变集合的2种方法:

如果实例恰好是一些写API的集合(例如List),你可以尝试转换为这种类型:

list = enumerableInstance as IList<string>;

从IEnumerable中创建一个列表(例如,通过LINQ扩展方法toList():

var list = enumerableInstance.toList();

IEnumerable items = Enumerable.Empty(T);

List somevalues = new List();

items.ToList阀门()(someValues); items.ToList () .AddRange (someValues);