假设我有一个类

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

我有一个List<MyObject>,我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:很抱歉,这似乎是显而易见的。但是我现在没有编译器……


当前回答

从Reflector来源:

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

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

其他回答

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

我在文档中没有看到ToList()总是保证返回一个新列表。如果IEnumerable是一个List,检查它并返回相同的List可能会更有效。

令人担心的是,有时您可能希望绝对确保返回的List是原来List的!=。因为微软没有记录ToList将返回一个新的List,所以我们不能确定(除非有人找到了该文档)。即使现在可行,未来也可能发生变化。

new 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();
    }

然后在答录机上回答

obj: 45653674 obj [0]: 41149443 对象:45653674 对象[0]:41149443 objectList: 39785641 objectList [0]: 41149443 whatInt: 5

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

ToList将创建一个全新的列表。

如果列表中的项是值类型,它们将被直接更新,如果它们是引用类型,任何更改都将反映回被引用的对象中。

是的,它创建了一个新列表。这是有意为之。

该列表将包含与原始可枚举序列相同的结果,但将其具体化为一个持久(内存中)集合。这允许您多次使用结果,而不会产生重新计算序列的成本。

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