.NET为什么现有List上的IEnumerable.ToList()创建新数组

时间:2011-11-28 23:06:16

标签: extension-methods ienumerable

出于好奇,为什么在现有List上调用IEnumerable.ToList()不会返回相同的实例?同样适用于IEnuerable.ToArray()。从内存消耗的角度来看,这会不会更好?

我进行了以下快速测试:

  var things= new List<Thing>( new [] {new Thing(), new Thing()});
        Console.WriteLine(things.GetHashCode());

        things= things.ToList();
        Console.WriteLine(things.GetHashCode());

我得到了不同的对象实例。为什么不是简单的相同实例?

3 个答案:

答案 0 :(得分:9)

这是故意这样做以启用“复制列表”方案。

例如,我做foreach( var a in list ) list.Remove(a),我会在枚举进行过程中得到一个例外,说明“该集合已被修改”。

要解决此问题,请执行:foreach( var a in list.ToList() ) list.Remove(a)

如果你想要“转换为列表,如果它不是已经存在”的语义,你将不得不自己处理它。实际上,您实际上可以为此编写一个简洁的扩展方法:

public static IList<T> ToListIfNotAlready( this IEnumerable<T> source )
{
     var list = source as IList<T>;
     return list == null ? source.ToList() : list;
}

是的,它可能是另一种方式,但LINQ设计师选择了这种方法,并且完全有权这样做,因为在一般情况下这两种方法都没有明显的优势。

答案 1 :(得分:1)

由于在枚举枚举时无法修改枚举的内容,因此有时需要创建列表副本,以便迭代一个副本并修改另一个副本。 ToList()定义为返回 new 列表,该列表独立于原始列表。

答案 2 :(得分:0)

ToList()的行为与枚举无关。它完成了名称所暗示的,即它返回一个列表。它并不意味着每次调用都返回相同的列表;除此以外;列表实例必须存储在内部某处。与许多其他Linq功能相同。它返回一个新列表这一事实有利于与foreach枚举器一起使用。