【问题标题】:Does Enumerable.Select() create a new object and return it?Enumerable.Select() 是否创建一个新对象并返回它?
【发布时间】:2013-07-10 15:03:44
【问题描述】:

我正在使用 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。有人可以解释为什么会这样吗?

【问题讨论】:

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


    【解决方案1】:

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

    如果你想在赋值给Property3时复制s.Prop3的内容,使用:

     s.Prop3.ToList() 
    

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

    【讨论】:

      【解决方案2】:

      在上面的例子中,List2是List1的深拷贝还是浅拷贝?

      技术上两者都不是,因为 IEnumerable 尚未被枚举。这也适用于 Property3 值。一旦枚举,它似乎将是一个深层副本。

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

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

      【讨论】:

        猜你喜欢
        • 2017-09-10
        • 1970-01-01
        • 2023-03-31
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多