【问题标题】:What's the Best Way to Add One Item to an IEnumerable<T>?将一项添加到 IEnumerable<T> 的最佳方法是什么?
【发布时间】:2013-02-21 11:15:19
【问题描述】:

以下是我如何将一项添加到 IEnumerable 对象:

//Some IEnumerable<T> object
IEnumerable<string> arr = new string[] { "ABC", "DEF", "GHI" };

//Add one item
arr = arr.Concat(new string[] { "JKL" });

这很尴尬。但是,我没有看到类似 ConcatSingle() 的方法。

有没有更简洁的方法将单个项目添加到 IEnumerable 对象?

【问题讨论】:

  • @Chris:我回滚了。从 SO 中删除该功能是有原因的。
  • 没有意识到该功能已被添加。谢谢指正。

标签: c# extension-methods ienumerable


【解决方案1】:

IEnumerable不可变 集合,这意味着您不能添加或删除项目。相反,您必须为此创建一个新集合,只需转换为列表以添加:

var newCollection = arr.ToList();
newCollection.Add("JKL"); //is your new collection with the item added

【讨论】:

  • 也许我遗漏了一些东西....但是 Add 不会返回新列表....msdn.microsoft.com/en-us/library/vstudio/…
  • Add 不会返回新列表,但因为 List 是一个 可变 集合,您可以简单地引用 List 对象来访问“新列表” .从这个意义上说,这个答案有点迂腐(因为很明显,OP 是在询问如何从另一个 IEnumerable 和一个额外的对象创建一个新的 IEnumerable)。
  • > IEnumerableimmutable 集合——错了,它不是一个集合,它是一个接口。实现它的类的对象可能是不可变的(如 Array)或可变的(如 List),这取决于实现。
【解决方案2】:

写一个扩展方法ConcatSingle :)

public static IEnumerable<T> ConcatSingle<T>(this IEnumerable<T> source, T item)
{
    return source.Concat(new [] { item } );
}

但你需要更加小心你的术语。
您不能将项目添加到 IEnumerable&lt;T&gt;Concat 创建一个新实例。

例子:

var items = Enumerable.Range<int>(1, 10)
Console.WriteLine(items.Count()); // 10
var original= items;
items = items.ConcatSingle(11);
Console.WriteLine(original.Count());   // 10
Console.WriteLine(items.Count()); // 11

如您所见,我们保存在 original 中的原始枚举没有改变。

【讨论】:

    【解决方案3】:

    由于IEnumerable是只读的,需要转换成列表。

    var new_one = arr.ToList().Add("JKL");
    

    或者你可以得到一个extension method的赞;

    public static IEnumerable<T> Append<T>(this IEnumerable<T> source, params T[] item)
    {
        return source.Concat(item);
    }
    

    【讨论】:

    • IEnumerable&lt;T&gt; 是只读的。这并不意味着它是不可变的。不可变集合是永远不会改变的集合。 IEnumerable&lt;T&gt; 甚至不保证引用不能被类型转换为可变类型,更不用说底层集合不会改变了。
    【解决方案4】:

    不,这与使用内置语言/框架功能一样简洁。

    如果您愿意,您可以随时创建扩展方法:

    arr = arr.Append("JKL");
    // or
    arr = arr.Append("123", "456");
    // or
    arr = arr.Append("MNO", "PQR", "STU", "VWY", "etc", "...");
    
    // ...
    
    public static class EnumerableExtensions
    {
        public static IEnumerable<T> Append<T>(
            this IEnumerable<T> source, params T[] tail)
        {
            return source.Concat(tail);
        }
    }
    

    【讨论】:

    • System.Linq 命名空间中有这样的方法
    【解决方案5】:

    您正在将一个数组分配给一个 IEnumerable。为什么不用 Array 类型而不是 IEnumerable?

    否则,如果要更改集合,可以使用 IList(或 List)。

    当我需要阅读时,我只将 IEnumerable 用于方法参数,而当我需要更改其中的项目时,我将其用于 IList(或 List)。

    【讨论】:

      【解决方案6】:

      Append() - 正是您所需要的,它已被添加到 .NET Standard(2017 年)中,因此您不再需要编写自己的扩展方法。你可以这样做:

      arr = arr.Append("JKL");

      由于 .NET 是开源的,您可以在这里查看实现(它比上面建议的自定义方法更复杂): https://github.com/dotnet/runtime/blob/master/src/libraries/System.Linq/src/System/Linq/AppendPrepend.cs

      【讨论】:

      • 有趣,谢谢。看起来新的 .Net 版本正在将链表附加到给定 IEnumerable 的开头和结尾。
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2013-08-22
      • 2010-10-04
      • 1970-01-01
      • 2018-08-10
      • 2011-10-19
      • 1970-01-01
      • 2010-09-18
      相关资源
      最近更新 更多