【发布时间】:2016-11-29 06:16:42
【问题描述】:
我正在用 C# 编写函数式代码。我的许多类都是不可变的,具有返回实例的修改副本的方法。
例如:
sealed class A
{
readonly X x;
readonly Y y;
public class A(X x, Y y)
{
this.x = x;
this.y = y;
}
public A SetX(X nextX)
{
return new A(nextX, y);
}
public A SetY(Y nextY)
{
return new A(x, nextY);
}
}
这是一个简单的例子,但是想象一个更大的类,有更多的成员。
问题在于构建这些修改后的副本非常冗长。大多数方法只更改一个值,但我必须将 all 未更改的值传递给构造函数。
在使用修饰符方法构造不可变类时,是否有一种模式或技术可以避免所有这些样板?
注意:我不想将struct 用于reasons discussed elsewhere on this site。
更新:我后来发现这在 F# 中被称为“复制和更新记录表达式”。
【问题讨论】:
-
我会质疑是否需要拥有这些“setter”,因为您已经为所有内容编写了它们。实际上,您应该对类型执行复杂的操作,而不仅仅是任意“设置”一个值。对于一个通用的对,它只需要一个构造函数。
-
@Servy 抱歉,这是示例的限制。大多数修饰符更复杂,或特定于任务。请想象我举了一个更好的例子:)
-
是的。使用 F#。现在是认真的。 C# 首先是有状态的 OOP 语言。虽然它确实具有一些函数式特性,但它远不是一种好的函数式语言。
-
今天的语言中没有太多可以在不可变类型上构建“with”方法的语法。如果您查看 Roslyn 源代码,您会发现有很多这样的方法,其中包含样板代码。正如 Andrey 在上面的评论中所建议的那样,样板是由工具生成的;这本身就表明该语言可能缺少一个特征。设计团队意识到了缺点;如果您想提倡功能以改进这一点,请考虑参与 github 上的 Roslyn 论坛。
-
如前所述,使用 F# 创建类,然后根据需要从 C# 中使用它们。
标签: c# oop design-patterns functional-programming immutability