有没有办法在C#中用关键字模拟F#?我知道它可能不会那么优雅,但我想知道是否有办法处理创建新的不可变数据结构副本.
F#中的记录是detailed here.
这是我正在尝试做的一个例子.我们将通过接口创建“不可变”的数据视图,同时保持具体类的可变性.这让我们可以在本地进行变异(在工作时),然后返回一个不可变的接口.这就是我们在C#中处理不变性的问题.
public interface IThing { double A { get; } double B { get; } } public class Thing : IThing { double A { get; set; } double B { get; set; } }
但是,当需要对数据进行更改时,来回转换它的类型(或可变性!)是不安全的,将类的每个属性手动转换为新实例也是一种痛苦.如果我们添加一个新的怎么办?我是否必须追踪每次操纵?当我真的只需要以前所拥有的东西时,我不想创造未来的头痛,但是[有些变化].
例:
// ... IThing item = MethodThatDoesWork(); // Now I want to change it... how? This is ugly and error/change prone: IThing changed = new Thing { A = item.A,B = 1.5 }; // ...
什么是实现这一目标的合理策略?你过去用过什么?
解决方法
由于没有语法糖,我知道你必须要么:
>手工完成(见下文)
>使用一些反射/自动化器(不是这个的粉丝)
>使用一些AOP技术(既不是那些人的粉丝)
至少这是我现在能想到的.
我不认为最后两个是个好主意,因为你带来了大机器来解决一个非常容易的问题.
是的,当你有数千个数据结构时,你可能会重新考虑这个,但如果你只有几个,我就不会使用它.
所以剩下的基本上是智能构造函数和类似的东西 – 这里有一个简单的例子说明你可以做到这一点(请注意,你并不需要所有这些 – 选择) – 它基本上错过了使用null / nullable来查看根据你的需要 – 更好的选择可能是重载或类似选项< T>数据类型,但现在我认为你得到它:
class MyData { private readonly int _intField; private readonly string _stringField; public MyData(int intField,string stringField) { _intField = intField; _stringField = stringField; } public MyData With(int? intValue = null,string stringValue = null) { return new MyData( intValue ?? _intField,stringValue ?? _stringField); } // should obvIoUsly be put into an extension-class of some sort public static MyData With(/*this*/ MyData from,int? intValue = null,string stringValue = null) { return from.With(intValue,stringValue); } public int IntField { get { return _intField; } } public string StringField { get { return _stringField; } } }