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

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

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

我们可以使用 items.Add(item)

之类的方法

List&lt; T&gt;

类似
有帮助吗?

解决方案

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

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??

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

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

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

其他提示

类型 IEnumerable&lt; T&gt; 不支持此类操作。 IEnumerable&lt; T&gt; 接口的目的是允许消费者查看集合的内容。不要修改值。

当您执行.ToList()。Add()等操作时,您将创建一个新的 List&lt; T&gt; 并向该列表添加值。它与原始列表没有关联。

您可以使用添加扩展程序方法创建一个具有附加值的新 IEnumerable&lt; T&gt;

items = items.Add("msg2");

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

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

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

修改

我不断忘记Add不是 IEnumerable&lt; T&gt; 的典型扩展方法,因为它是我最终定义的第一个。这是

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

您是否考虑过使用 ICollection&lt; T&gt; IList&lt; T&gt; 接口,它们的存在是因为您希望在 IEnumerable&lt; T&gt; 上有 Add 方法。

IEnumerable&lt; T&gt; 用于将类型“标记”为......井,可枚举或只是一系列项目,而不必保证真实底层对象是否支持添加/删除项目。还要记住,这些接口实现了 IEnumerable&lt; T&gt; ,因此您可以获得 IEnumerable&lt; T&gt; 所带来的所有扩展方法。

IEnumerable IEnumerable&lt; T&gt; 上的几个简短的甜扩展方法为我做了:

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

在.net Core中,有一个方法 Enumerable.Append 就是这样做的。

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

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

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

您不仅可以添加像您所述的项目,还可以添加项目到 List&lt; T&gt; (或几乎任何其他非只读集合)枚举器for,枚举器失效(从那时起抛出 InvalidOperationException )。

如果要汇总某些类型的数据查询结果,可以使用 Concat 扩展方法:

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

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

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

IEnumerable<T> items = new T[]{new T("msg")};
items = items.Append(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;

最简单的方法就是

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

当然,你可以(我将你的T-business留在一边):

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

    return list.Select(i => i);
}
许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top