with 表达式 与 new 关键字

Ebr*_*yed 1 c# heap-memory c#-9.0

我正在阅读有关“C#9.0 中的新增功能”的开发博客,然后我注意到“with expression”。

\n\n
public data class Person\n{\n    public string FirstName { get; init; }\n    public string LastName { get; init; }\n}\nvar otherPerson = person with { LastName = "Hanselman" };\n
Run Code Online (Sandbox Code Playgroud)\n\n

他们说

\n\n
\n

记录隐式定义受保护的 \xe2\x80\x9ccopy 构造函数\xe2\x80\x9d \xe2\x80\x93 一个构造函数,该构造函数接受现有记录对象并将其逐个字段复制到新记录对象:

\n
\n\n
protected Person(Person original) { /* copy all the fields */ } // generated\n
Run Code Online (Sandbox Code Playgroud)\n\n
\n

with 表达式导致调用复制构造函数,然后在顶部应用对象初始值设定项以相应地更改属性。

\n
\n\n

我的问题是,\n“with”是否从“堆”复制整个旧对象,然后用新值(如果存在)修改它们,然后创建新实例?(IMO...我认为这是一种昂贵的方法)\nor“with”是否会让您只写更少的行而没有任何内存泄漏?

\n\n

如果我的第一个假设是正确的,那么使用“with”或“new”会更好,例如:var obj = new foo();

\n

Gar*_*tty 5

表达式with创建一个新实例,因此旧实例仍将保持不变,它不会发生突变\xe2\x80\x94,考虑到其目的是处理不可变数据,这是有道理的。

\n\n

这不是内存泄漏,除非您以某种方式保留旧实例。它可能会增加 GC 流失率,但这不一定是坏事,而且从不变性中轻松推理所带来的收益通常是值得的。

\n\n

(当然,我假设编译器这里有优化的潜力,如果编译器可以证明旧值不会被使用,但我怀疑这样的事情至少已经实现了\xe2\x80\x94) 。

\n\n

编辑:

\n\n

这是SharpLab 反编译(进行一些更改以使其正常工作)。您可以看到它编译后的结果非常简单。

\n

  • 简单的判断方法是使用“with”分支模拟一个 Sharplab 示例,并检查生成的 C# 选项卡。我会这样做并提供链接,但很难通过手机做到这一点 (2认同)