gpt4 book ai didi

c# - 如何有效地 "change"不可变对象(immutable对象)?

转载 作者:行者123 更新时间:2023-11-30 21:54:28 24 4
gpt4 key购买 nike

是否有任何聪明的设计模式或某种通用方法来“修改”不可变对象(immutable对象)?

背景:
让我们有一组不同的(没有共同的 base)不可变对象(immutable对象),每个对象都有不同的 {get; private set;} 属性和一个公共(public)构造函数(接受一组属性值)。这些对象是并且应该保持不变,但有时,在某种特殊模式下,它们的值需要“改变”。

这种修改意味着只创建新对象,除了更新的属性(如 o = new c(o.a, updateB, updateC, o.d, ...)之外,其值与原始对象相同).

我可以想象就地调用构造函数,或定义一个(例如扩展)方法返回新实例,接受一些参数来识别更新的属性并通过反射修改它/它们,但一切似乎都非常具体和在系统范围内用于“任何”不可变的并不优雅。我喜欢 linq 处理的方式,例如IEnumerable 和您可以生成并完全重新转换输入集合的链。有什么想法吗?

最佳答案

据我所知,类似的一个例子是 Roslyn,Microsoft 当前的 C# 编译器,它广泛使用不可变数据结构。语法树类为每个属性提供了方便的方法,用于返回一个只更改一个属性的新实例,例如

var cu = Syntax.CompilationUnit()
.AddMembers(
Syntax.NamespaceDeclaration(Syntax.IdentifierName("ACO"))
.AddMembers(
Syntax.ClassDeclaration("MainForm")
.AddBaseListTypes(Syntax.ParseTypeName("System.Windows.Forms.Form"))
.WithModifiers(Syntax.Token(SyntaxKind.PublicKeyword))
.AddMembers(
Syntax.PropertyDeclaration(Syntax.ParseTypeName("System.Windows.Forms.Timer"), "Ticker")
.AddAccessorListAccessors(
Syntax.AccessorDeclaration(SyntaxKind.GetAccessorDeclaration).WithSemicolonToken(Syntax.Token(SyntaxKind.SemicolonToken)),
Syntax.AccessorDeclaration(SyntaxKind.SetAccessorDeclaration).WithSemicolonToken(Syntax.Token(SyntaxKind.SemicolonToken))),
Syntax.MethodDeclaration(Syntax.ParseTypeName("void"), "Main")
.AddModifiers(Syntax.Token(SyntaxKind.PublicKeyword))
.AddAttributes(Syntax.AttributeDeclaration().AddAttributes(Syntax.Attribute(Syntax.IdentifierName("STAThread"))))
.WithBody(Syntax.Block())
)
)
);

或者在你的情况下:

o = o.WithB(updateB).WithC(updateC);

我认为这对于预期的用例来说读起来非常好(仅更新几个属性,同时保持其他所有内容相同)。当有 许多 属性时,它尤其胜过 »always have to call the ctor« 方法。

我认为在 Roslyn 中,这些都是自动生成的。如果有必要,您或许可以对 T4 做类似的事情。

关于c# - 如何有效地 "change"不可变对象(immutable对象)?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/33080656/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com