[c#] ToList() - 它是否创建一个新列表?


Answers

来自Reflector'd的资料来源:

public static List<TSource> ToList<TSource>(this IEnumerable<TSource> source)
{
    if (source == null)
    {
        throw Error.ArgumentNull("source");
    }
    return new List<TSource>(source);
}

所以是的,你的原始列表不会被更新(即增加或删除),但是被引用的对象将会被更新。

Question

假设我有一堂课

public class MyObject
{
   public int SimpleInt{get;set;}
}

我有一个List<MyObject>和I ToList() ,然后更改其中一个SimpleInt ,我的更改会传播回原始列表。 换句话说,以下方法的输出是什么?

public void RunChangeList()
{
  var objs = new List<MyObject>(){new MyObject(){SimpleInt=0}};
  var whatInt = ChangeToList(objs );
}
public int ChangeToList(List<MyObject> objects)
{
  var objectList = objects.ToList();
  objectList[0].SimpleInt=5;
  return objects[0].SimpleInt;

}

为什么?

P / S:如果看起来很明显,我很抱歉。 但我现在没有编译器了。




在源对象是真正的IEnumerable的情况下(即,不仅仅是一个集合打包为一个可枚举的集合),ToList()可能不会返回与原始IEnumerable中相同的对象引用。 它将返回一个新的对象列表,但这些对象可能与IEnumerable在枚举时再次枚举时产生的对象可能不同或甚至相等




是的,它创建了一个新的列表。 这是设计。

该列表将包含与原始可枚举序列相同的结果,但会实现为持久(内存)集合。 这使您可以多次使用结果,而不会产生重新计算序列的成本。

LINQ序列的美妙之处在于它们是可组合的。 通常,您获得的IEnumerable<T>是组合多个过滤,排序和/或投影操作的结果。 ToList()ToArray()等扩展方法允许您将计算出的序列转换为标准集合。




我没有看到ToList()始终保证返回一个新列表的文档中的任何地方。 如果一个IEnumerable是一个List,检查这个并且简单地返回相同的List可能更有效率。

担心的是,有时您可能希望确定返回的List是!=原始列表。 因为微软没有记录ToList会返回一个新的列表,我们不能确定(除非有人发现该文档)。 即使它现在有效,它也可能在未来发生变化。

新的List(IEnumerable enumerablestuff)保证返回一个新的List。 我会用这个来代替。




只是偶然发现了这个旧帖子,想到要加两分钱。 一般来说,如果我有疑问,我很快在任何对象上使用GetHashCode()方法来检查身份。 所以对于以上 -

    public class MyObject
{
    public int SimpleInt { get; set; }
}


class Program
{

    public static void RunChangeList()
    {
        var objs = new List<MyObject>() { new MyObject() { SimpleInt = 0 } };
        Console.WriteLine("objs: {0}", objs.GetHashCode());
        Console.WriteLine("objs[0]: {0}", objs[0].GetHashCode());
        var whatInt = ChangeToList(objs);
        Console.WriteLine("whatInt: {0}", whatInt.GetHashCode());
    }

    public static int ChangeToList(List<MyObject> objects)
    {
        Console.WriteLine("objects: {0}", objects.GetHashCode());
        Console.WriteLine("objects[0]: {0}", objects[0].GetHashCode());
        var objectList = objects.ToList();
        Console.WriteLine("objectList: {0}", objectList.GetHashCode());
        Console.WriteLine("objectList[0]: {0}", objectList[0].GetHashCode());
        objectList[0].SimpleInt = 5;
        return objects[0].SimpleInt;

    }

    private static void Main(string[] args)
    {
        RunChangeList();
        Console.ReadLine();
    }

并在我的机器上回答 -

  • 目标:45653674
  • objs [0]:41149443
  • 对象:45653674
  • 对象[0]:41149443
  • objectList:39785641
  • objectList [0]:41149443
  • whatInt:5

所以基本上,列表中携带的对象在上面的代码中保持不变。 希望这种方法有帮助。




创建一个新列表,但其中的项目是对原始项目的引用(就像在原始列表中一样)。 对列表本身的更改是独立的,但对于这两个列表中的项目都会发现更改。




Links



Tags

c# c#   linq