Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/linq/3.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# ToList()--它是否创建新列表?_C#_Linq - Fatal编程技术网

C# ToList()--它是否创建新列表?

C# ToList()--它是否创建新列表?,c#,linq,C#,Linq,假设我有一节课 public class MyObject { public int SimpleInt{get;set;} } 我有一个列表,我ToList()它,然后更改其中一个SimpleInt,我的更改将传播回原始列表。换句话说,以下方法的输出是什么 public void RunChangeList() { var objs = new List<MyObject>(){new MyObject(){SimpleInt=0}}; var whatInt =

假设我有一节课

public class MyObject
{
   public int SimpleInt{get;set;}
}
我有一个
列表
,我
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;

}
public void RunChangeList()
{
var objs=new List(){new MyObject(){SimpleInt=0}};
var whatInt=变更列表(objs);
}
public int ChangeToList(列出对象)
{
var objectList=objects.ToList();
objectList[0]。SimpleInt=5;
返回对象[0]。SimpleInt;
}
为什么?


p/S:我很抱歉,如果这似乎是显而易见的发现。但是我现在没有带编译器…

ToList
将始终创建一个新列表,它不会反映对集合的任何后续更改

但是,它将反映对对象本身的更改(除非它们是可变结构)

换句话说,如果用不同的对象替换原始列表中的对象,
ToList
仍将包含第一个对象。

但是,如果修改原始列表中的一个对象,则
ToList
仍将包含相同的(已修改的)对象。

将创建一个新列表,但其中的项目是对原始项目的引用(与原始列表中的一样)。对列表本身的更改是独立的,但对项目的更改将在两个列表中找到更改。

是的,它会创建一个新列表。这是精心设计的。

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


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

是,
ToList
将创建一个新列表,但由于在本例中
MyObject
是一个引用类型,因此新列表将包含对与原始列表相同的对象的引用

更新新列表中引用的对象的
SimpleInt
属性也会影响原始列表中的等效对象


(如果
MyObject
声明为
struct
而不是
class
,则新列表将包含原始列表中元素的副本,更新新列表中元素的属性不会影响原始列表中的等效元素。)

ToList
将创建一个全新的列表

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

 var objectList = objects.ToList();
  objectList[0].SimpleInt=5;
这也将更新原始对象。新列表将包含对其中包含的对象的引用,就像原始列表一样。您可以更改其中一个元素,更新将反映在另一个元素中


现在,如果您更新了一个列表(添加或删除一个项目),而该列表不会反映在另一个列表中。

我认为这相当于询问ToList是进行深度复制还是进行浅层复制。由于ToList无法克隆MyObject,它必须进行浅层复制,因此创建的列表包含与原始列表相同的引用,因此代码从Reflector的源返回5。

public static List<TSource> ToList<TSource>(this IEnumerable<TSource> source)
{
    if (source == null)
    {
        throw Error.ArgumentNull("source");
    }
    return new List<TSource>(source);
}
公共静态列表列表(此IEnumerable源代码)
{
if(source==null)
{
抛出错误。ArgumentNull(“源”);
}
返回新列表(源);
}

因此,是的,您的原始列表不会更新(即添加或删除),但引用的对象会更新。

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

令人担忧的是,有时您可能希望绝对确保返回的列表是!=到原始列表。因为微软没有文档说明ToList会返回一个新的列表,所以我们不能确定(除非有人找到文档)。它也可能在未来发生变化,即使它现在起作用


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

接受的答案根据OP的示例正确地回答了OP的问题。但是,它仅适用于混凝土集料;当源序列的元素还没有被实例化时(由于延迟执行),它不起作用。对于后者,每次调用
ToList
(或枚举序列)时可能会得到一组新的项

以下是对OP代码的修改,以演示此行为:

public static void RunChangeList()
{
    var objs = Enumerable.Range(0, 10).Select(_ => new MyObject() { SimpleInt = 0 });
    var whatInt = ChangeToList(objs);   // whatInt gets 0
}

public static int ChangeToList(IEnumerable<MyObject> objects)
{
    var objectList = objects.ToList();
    objectList.First().SimpleInt = 5;
    return objects.First().SimpleInt;
}
public静态void RunChangeList()
{
var objs=Enumerable.Range(0,10).Select(=>newmyobject(){SimpleInt=0});
var whatInt=ChangeToList(objs);//whatInt得到0
}
公共静态int ChangeToList(IEnumerable对象)
{
var objectList=objects.ToList();
objectList.First().SimpleInt=5;
返回objects.First().SimpleInt;
}

虽然上面的代码可能看起来是人为的,但在其他场景中,这种行为可能是一个微妙的错误。请参阅,了解导致任务重复生成的情况。

只是偶然发现这篇旧文章并想到了添加
    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();
    }