我的问题如上所述。例如
IEnumerable<T> items = new T[]{new T("msg")};
items.ToList().Add(new T("msg2"));
但毕竟里面只有一项。我们能不能有一个items.Add(item)方法,比如List<T>?
我的问题如上所述。例如
IEnumerable<T> items = new T[]{new T("msg")};
items.ToList().Add(new T("msg2"));
但毕竟里面只有一项。我们能不能有一个items.Add(item)方法,比如List<T>?
当前回答
您不仅不能像您的状态那样添加项,而且如果您将项添加到List<T>(或几乎任何其他非只读集合),并且您有一个现有的枚举器,则枚举器将失效(从那时开始抛出InvalidOperationException)。
如果您正在聚合来自某种类型的数据查询的结果,您可以使用Concat扩展方法:
编辑:我最初在示例中使用了Union扩展,这是不正确的。我的应用程序广泛地使用它来确保重叠的查询不会重复结果。
IEnumerable<T> itemsA = ...;
IEnumerable<T> itemsB = ...;
IEnumerable<T> itemsC = ...;
return itemsA.Concat(itemsB).Concat(itemsC);
其他回答
在.net Core中,有一个方法Enumerable。附加就是这样做的。
该方法的源代码可在GitHub.....上获得实现(比其他答案中的建议更复杂)值得一看:)。
关于为什么不能(也不应该!)向IEnumerable中添加项,其他人已经给出了很好的解释。我只会补充说,如果您希望继续为表示集合的接口编码,并且想要一个add方法,那么您应该为ICollection或IList编码。作为额外的财源,这些接口实现了IEnumerable。
我只是想说,除了Enumerable。Concat扩展方法,似乎有另一个方法名为Enumerable。在. net Core 1.1.1中添加。后者允许您将单个项连接到现有序列。所以Aamol的答案也可以写成
IEnumerable<T> items = new T[]{new T("msg")};
items = items.Append(new T("msg2"));
不过,请注意,这个函数不会改变输入序列,它只是返回一个包装器,将给定的序列和附加的项放在一起。
不能,因为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”。此外,新对象将跟踪数组中的变化(即无论何时枚举它,您都将看到项目的当前值)。
你是否考虑过使用ICollection<T>或IList<T>接口来代替,它们存在的原因正是你想在IEnumerable<T>上有一个Add方法。
IEnumerable<T>用于“标记”一个类型为…嗯,可枚举的,或者只是一个项的序列,而不必保证真正的底层对象是否支持添加/删除项。还要记住,这些接口实现了IEnumerable<T>,所以你得到了所有的扩展方法,你也得到了IEnumerable<T>。