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

本文关键字:对象 新对象 返回 Select Enumerable 创建 是否 一个 | 更新日期: 2023-09-27 18:22:00

我正在使用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,则结果。Property3也变为null。有人能解释为什么会发生这种情况吗?

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

对Select()的调用实际上并不会导致在使用点枚举s.Prop3,相反,您可以将其视为对s.Prop3的视图,以便稍后访问Property3时,它将在该点枚举s.Prop3。

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

 s.Prop3.ToList() 

相反这会将s.Prop3逐元素复制到一个新列表中,这意味着如果稍后修改s.Prop3,它将不会对Property3产生影响。

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

从技术上讲,两者都没有,因为IEnumerable还没有被枚举。这也适用于Property3值。一旦列举出来,它似乎就是一个深度复制。

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

这是因为您可能在设置Prop3=null之后枚举result.List2。这完全是基于对Select实际作用的明显误解——它不是在执行行时创建新的集合,而是在调用ToListToArrayforeach(var x in y)等时(即每当枚举时)如何创建这样的集合的说明。