【问题标题】:Does LINQ new up memory when creating returns创建返回时 LINQ 是否新增内存
【发布时间】:2011-01-21 17:33:15
【问题描述】:

LINQ 是否实际上将结果的深层复制到不同的列表/数组/等,或者它只是给我一个列表/数组/等。由对原作的引用组成?

【问题讨论】:

  • .NET 中没有任何东西——除了序列化——永远不会自动创建任何东西的深层副本。原因之一是自动构建深层副本并非易事。
  • @bzlm - 所以当我编辑 LINQ 查询的结果时,我实际上是在编辑原始集合成员的值?
  • 是的,你是。尝试一下。 :)

标签: linq deep-copy shallow-copy


【解决方案1】:

这将取决于您是否(以及如何)使用 Select 来投影结果。

如果您不在投影中创建新对象,则结果将引用与原始集合相同的对象。

但是,如果您在项目中创建新对象,那么显然它们将不一样。

这里返回的集合将包含对_myCollection中相同对象的引用:

from m in _myCollection
where m.SomeFilterCriteria
select m

在这些情况下返回的集合不会:

from m in _myCollection
where m.SomeFilterCriteria
select new { m.Prop1, m.Prop2 }

在这种情况下,值得指出的是,新匿名对象的 Prop1 和 Prop2(如果它们是引用类型)将包含对 与原始对象相同对象的引用。只有集合中的顶级引用会有所不同。

基本上 - .Net 中除了序列化程序(如此处其他地方提到的)之外的任何内容都不会“深度”复制,除非您实现它。

from m in _myCollection
where m.SomeFilterCriteria
select m.Clone()

再一次,假设在这里进行任何“深度”复制是错误的。当然,Clone 的实现将在类中,可以是任何东西,包括深度复制,但没有给出。

【讨论】:

  • 在你的最后一个例子中,我认为Clone() 只执行了浅拷贝。
  • 克隆将复制,但它是为了这样做而实现的。没有默认的 .Clone - 您必须为要支持它的任何对象实现它。我的回答只针对集合中的顶级参考。 .Net 中没有“深度”副本。
  • @Joel B:添加到 qstarin 的评论中,MSDN article 明确指出“克隆可以实现为深拷贝或浅拷贝。”因此,不仅会克隆拷贝,但它已实现这样做,但根据 MSDN 文档,浅拷贝和深拷贝都是允许的实现。有趣的是,对象有一个受保护的MemberwiseClone 成员,用于制作浅拷贝。
  • @Brian - 对于Clone 执行的复制类型是否有标准/最佳实践? Clone 不允许编写自己的MemberwiseClone 实现吗?为什么不在框架中将MemberwiseClone 设为虚拟?
  • MemberwiseClone 以非常特定的方式运行,旨在用于实现克隆操作。将其设为虚拟将允许重写实现,然后派生类将无法依赖其行为本身。
【解决方案2】:

LINQ 是否实际上将结果的深层复制到不同的列表/数组/等,或者它只是给我一个列表/数组/等。由对原作的引用组成?

来自Enumerable.ToArray。 (类似文字见Enumerable.ToList

ToArray(IEnumerable) 方法强制立即进行查询评估并返回一个包含查询结果的数组。您可以将此方法附加到查询中,以获取查询结果的缓存副本。

嗯,这看起来确实令人困惑。

  1. 返回一个包含查询结果的数组
  2. 获取查询结果的缓存副本

从第一句话可以清楚地看出,查询中的项目没有复制

从第二句中,您获得了整个查询结果的副本,但这是一个浅表副本,因为查询中的项目没有复制

【讨论】:

    【解决方案3】:

    它返回的内容很大程度上取决于您所指的 LINQ 方法。但除了显式复制枚举的少数方法(例如ToListToArray)之外,一般模式是不将输入复制到新结构中。相反,它更喜欢惰性评估。

    【讨论】:

    • 如果你重新阅读这个问题,你会发现 ToList() 和 ToArray() 并不特别。 :)
    • @bzlm,不确定这个问题与我的答案的那一部分有何关系。在我对其余部分进行更广泛的陈述之前,我想将它们明确称为 2 种 LINQ 方法,它们热切地评估输入并为其生成一个新的集合结构。我没有说它做了一个深拷贝,所以不确定你指的是什么。
    • @JaredPar 问题是“LINQ 是否真的执行深层复制 [...] 还是只是给我一个列表 [...] 由对原始文件的引用组成”。您的答案是关于是否评估 enumerations。对吗?
    • @bzlm,如何评估枚举会影响 LINQ 操作返回的方式/内容,这是问题的实质。
    • @JaredPar 好吧,让我们同意不同意。 :)
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-09-13
    • 2018-02-08
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-10-04
    相关资源
    最近更新 更多