Enumerable.Select()是否创建了一个新对象并返回它?

时间:2013-07-10 15:03:45

标签: c# .net c#-4.0 lambda ienumerable

我正在使用Enumerable.Select()方法从现有列表创建新的IEnumerable列表。这是代码示例:

class ClassA
{
   IEnumerable<TypeA> List1;
   ....
}

class ClassB
{
   IEnumerable<TypeB> List2;
   ...
}

class TypeA
{
    //some properties;
    IEnumerable<TypeC> Prop3;
}

class TypeB
{ 
   //some properties;
   IEnumerable<TypeC> Property3;
}

.
.
.
.

ClassA input;  //input data object
ClassB result = new classB();
result.List2 = input.List1.Select(s =>
{
   new TypeB() 
   {
       Property1 = s.Prop1,
       Property2 = s.Prop2,
       Property3 = s.Prop3==null?null:s.Prop3.Select(c=>c)
   }
});

在上面的示例中,List2是List1的深拷贝还是浅拷贝?如果没有,我该如何获得深层复制?

此外,如果我在执行上述代码后设置Prop3 = null(在创建结果对象之后),则result.Property3也变为null。有人可以解释为什么会这样吗?

2 个答案:

答案 0 :(得分:2)

对Select()的调用实际上并不会导致s.Prop3在其使用的位置被枚举,而是你可以把它想象成s.Prop3的视图,这样以后,当你访问Property3时,它会此时枚举s.Prop3。

如果要在将s.Prop3分配给Property3时复制其内容,请使用:

 s.Prop3.ToList() 

...来代替。这会将s.Prop3(逐个元素)复制到一个新列表中,这意味着如果稍后修改s.Prop3,它将对Property3没有影响。

答案 1 :(得分:1)

  

在上面的示例中,List2会是List1的深层副本还是浅层副本?

从技术上讲,既不是因为没有枚举IEnumerable。这也适用于Property3值。枚举后,它似乎是一个深层副本。

  

如果我在上面的代码执行后设置Prop3 = null(创建结果对象后),result.Property3也会变为空。

这是因为您可能在设置Prop3 = null后枚举result.List2。这完全基于对Select 实际所做的明显误解 - 它不会在执行行时创建新的集合,而是指示如何在ToListToArrayforeach(var x in y)等被调用时(即,无论何时枚举)都会创建此类集合。